diff --git a/ClientApp/src/app/app.module.ts b/ClientApp/src/app/app.module.ts
index f4fdf93..61cdaf8 100644
--- a/ClientApp/src/app/app.module.ts
+++ b/ClientApp/src/app/app.module.ts
@@ -10,6 +10,7 @@ import { HomeComponent } from './components/home/home.component';
import { CounterComponent } from './components/counter/counter.component';
import { SanctionedEntitiesComponent } from './components/sanctioned-entities/sanctioned-entities.component';
import { JumbotronCounterComponent } from './components/jumbotron-counter/jumbotron-counter.component';
+import { CreateSanctionedEntityComponent } from './components/create-sanctioned-entity/create-sanctioned-entity.component';
@NgModule({
@@ -19,7 +20,8 @@ import { JumbotronCounterComponent } from './components/jumbotron-counter/jumbot
HomeComponent,
CounterComponent,
SanctionedEntitiesComponent,
- JumbotronCounterComponent
+ JumbotronCounterComponent,
+ CreateSanctionedEntityComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
@@ -29,6 +31,7 @@ import { JumbotronCounterComponent } from './components/jumbotron-counter/jumbot
{ path: '', component: HomeComponent, pathMatch: 'full' },
{ path: 'counter', component: CounterComponent },
{ path: 'sanctioned-entities', component: SanctionedEntitiesComponent },
+ { path: 'create-sanction-entity', component: CreateSanctionedEntityComponent }
])
],
providers: [],
diff --git a/ClientApp/src/app/components/counter/counter.component.html b/ClientApp/src/app/components/counter/counter.component.html
index 89b9c80..3dd9ffa 100644
--- a/ClientApp/src/app/components/counter/counter.component.html
+++ b/ClientApp/src/app/components/counter/counter.component.html
@@ -2,6 +2,6 @@
Counter
This is a simple example of an Angular component.
-Current count: {{ currentCount }}
+Current count: {{ counter$ | async}}
diff --git a/ClientApp/src/app/components/counter/counter.component.ts b/ClientApp/src/app/components/counter/counter.component.ts
index 1f336aa..94df8bc 100644
--- a/ClientApp/src/app/components/counter/counter.component.ts
+++ b/ClientApp/src/app/components/counter/counter.component.ts
@@ -1,13 +1,21 @@
-import { Component } from '@angular/core';
+import { Component, Input, OnDestroy } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { CounterService } from 'src/app/services/counter.service';
@Component({
selector: 'app-counter-component',
templateUrl: './counter.component.html'
})
export class CounterComponent {
- public currentCount = 0;
+ public counter$: Observable;
+
+ @Input('minimalistMode') minimalistMode: boolean = false;
+
+ constructor(private counterService: CounterService) {
+ this.counter$ = this.counterService.getCounter();
+ }
public incrementCounter() {
- this.currentCount++;
+ this.counterService.increaseCounter();
}
}
diff --git a/ClientApp/src/app/components/create-sanctioned-entity/create-sanctioned-entity.component.html b/ClientApp/src/app/components/create-sanctioned-entity/create-sanctioned-entity.component.html
new file mode 100644
index 0000000..04791c6
--- /dev/null
+++ b/ClientApp/src/app/components/create-sanctioned-entity/create-sanctioned-entity.component.html
@@ -0,0 +1,31 @@
+
+
+
\ No newline at end of file
diff --git a/ClientApp/src/app/components/create-sanctioned-entity/create-sanctioned-entity.component.ts b/ClientApp/src/app/components/create-sanctioned-entity/create-sanctioned-entity.component.ts
new file mode 100644
index 0000000..7bb44d5
--- /dev/null
+++ b/ClientApp/src/app/components/create-sanctioned-entity/create-sanctioned-entity.component.ts
@@ -0,0 +1,41 @@
+import { Component } from '@angular/core';
+import { SanctionedEntity } from '../../models/sanctioned-entity';
+import { SanctionedEntitiesService } from '../../services/sanctioned-entities.service';
+import { NgForm } from '@angular/forms';
+import { Router } from '@angular/router';
+import { catchError, throwError } from 'rxjs';
+
+@Component({
+ selector: 'app-sanctioned-entities',
+ templateUrl: './create-sanctioned-entity.component.html'
+})
+export class CreateSanctionedEntityComponent {
+ public newEntity: SanctionedEntity;
+ public serverError: string|null = null;
+
+ constructor(private entitiesService: SanctionedEntitiesService, private router: Router) {
+ this.newEntity = { id: '', accepted: false, domicile: '', name: ''};
+ }
+
+ public save(form: NgForm): void {
+
+ if(form.valid && form.enabled){
+ this.entitiesService.createNewEntity(this.newEntity)
+ .pipe(
+ catchError(response => {
+ this.serverError = response.error.detail;
+
+ return throwError(response);
+ })
+ )
+ .subscribe(newEntity => {
+
+ if(newEntity){
+ this.router.navigate(['/sanctioned-entities']);
+ }
+
+ });
+ }
+ }
+
+}
diff --git a/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.html b/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.html
index 4d39017..f00c4f1 100644
--- a/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.html
+++ b/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.html
@@ -1,4 +1,15 @@
Current count:
-
Please include the counter here
+
{{ counter$ | async}}
+
+
+
+
+
+
diff --git a/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.ts b/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.ts
index 6884723..7d407f2 100644
--- a/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.ts
+++ b/ClientApp/src/app/components/jumbotron-counter/jumbotron-counter.component.ts
@@ -1,8 +1,16 @@
import { Component } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+import { CounterService } from 'src/app/services/counter.service';
@Component({
selector: 'app-jumbotron-counter',
templateUrl: './jumbotron-counter.component.html'
})
export class JumbotronCounterComponent {
+ public counter$: Observable;
+
+ constructor(private counterService: CounterService){
+ this.counter$ = this.counterService.getCounter();
+ }
+
}
diff --git a/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.html b/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.html
index 9699666..c012fdd 100644
--- a/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.html
+++ b/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.html
@@ -1,7 +1,9 @@
Sanctioned Entities
+
Loading...
+
diff --git a/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.ts b/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.ts
index ca699d1..3dbe241 100644
--- a/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.ts
+++ b/ClientApp/src/app/components/sanctioned-entities/sanctioned-entities.component.ts
@@ -14,4 +14,5 @@ export class SanctionedEntitiesComponent {
this.entities = entities;
});
}
+
}
diff --git a/ClientApp/src/app/services/counter.service.ts b/ClientApp/src/app/services/counter.service.ts
new file mode 100644
index 0000000..a0a4fe0
--- /dev/null
+++ b/ClientApp/src/app/services/counter.service.ts
@@ -0,0 +1,23 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Observable } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class CounterService {
+
+ private counterSubject: BehaviorSubject = new BehaviorSubject(0);
+ private counter$ = this.counterSubject.asObservable();
+
+ constructor() {
+
+ }
+
+ public getCounter(): Observable {
+ return this.counter$;
+ }
+
+ public increaseCounter() : void{
+ this.counterSubject.next(this.counterSubject.value + 1);
+ }
+}
diff --git a/ClientApp/src/app/services/sanctioned-entities.service.ts b/ClientApp/src/app/services/sanctioned-entities.service.ts
index 1a90e11..ea5e744 100644
--- a/ClientApp/src/app/services/sanctioned-entities.service.ts
+++ b/ClientApp/src/app/services/sanctioned-entities.service.ts
@@ -19,4 +19,10 @@ export class SanctionedEntitiesService {
const url = this.apiUrl + this.path;
return this.http.get(url);
}
+
+ public createNewEntity(newEntity: SanctionedEntity): Observable {
+ const url = this.apiUrl + this.path;
+
+ return this.http.post(url, newEntity);
+ }
}
diff --git a/Controllers/SanctionedEntitiesController.cs b/Controllers/SanctionedEntitiesController.cs
index e6946c6..089d709 100644
--- a/Controllers/SanctionedEntitiesController.cs
+++ b/Controllers/SanctionedEntitiesController.cs
@@ -1,4 +1,5 @@
-using ajgre_technical_interview.Services;
+using ajgre_technical_interview.Models;
+using ajgre_technical_interview.Services;
using Microsoft.AspNetCore.Mvc;
namespace ajgre_technical_interview.Controllers
@@ -8,10 +9,12 @@ namespace ajgre_technical_interview.Controllers
public class SanctionedEntitiesController : ControllerBase
{
private readonly IDatabaseService _databaseService;
+ private readonly ILogger _logger;
- public SanctionedEntitiesController(IDatabaseService databaseService)
+ public SanctionedEntitiesController(IDatabaseService databaseService, ILogger logger)
{
_databaseService = databaseService;
+ _logger = logger;
}
@@ -25,9 +28,27 @@ public async Task GetSanctionedEntities()
}
catch (Exception ex)
{
+ //A little logging is always nice to have!
+ _logger.LogError(ex, $"Exception occured in route '{nameof(GetSanctionedEntities)}'");
return Problem(ex.Message);
}
}
+
+ [HttpPost]
+ public async Task CreateSanctionEntity([FromBody] SanctionedEntity newSanctionEntity)
+ {
+ try
+ {
+ var newEntity = await _databaseService.CreateSanctionedEntityAsync(newSanctionEntity);
+ return Ok(newEntity);
+ }
+ catch (Exception ex)
+ {
+ //A little logging is always nice to have!
+ _logger.LogError(ex, $"Exception occured in route '{nameof(CreateSanctionEntity)}'");
+ return Problem(ex.Message);
+ }
+ }
}
}
diff --git a/Services/DatabaseService.cs b/Services/DatabaseService.cs
index 330647d..ab69938 100644
--- a/Services/DatabaseService.cs
+++ b/Services/DatabaseService.cs
@@ -29,6 +29,16 @@ public async Task GetSanctionedEntityByIdAsync(Guid id)
public async Task CreateSanctionedEntityAsync(SanctionedEntity sanctionedEntity)
{
+ //Validate that there is not a sanctioned entity with the same name and domicile already.
+ //Would normally seperate this validation into a step in a service sitting between DB and the controller.
+ var newEntityIsValid = !SanctionedEntities.Any(x => x.Name == sanctionedEntity.Name
+ && x.Domicile == sanctionedEntity.Domicile);
+
+ if (!newEntityIsValid)
+ {
+ throw new Exception("A sanctioned entity with the same name and domicile already exists.");
+ }
+
SanctionedEntities.Add(sanctionedEntity);
return await Task.FromResult(sanctionedEntity);
}