Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,6 @@ _Pvt_Extensions

# FAKE - F# Make
.fake/

/ClientApp/.angular/cache/14.0.3

8 changes: 6 additions & 2 deletions ajgre-technical-interview.csproj → API/API.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<SpaRoot>ClientApp\</SpaRoot>
<SpaRoot>..\ClientApp\</SpaRoot>
<SpaProxyServerUrl>https://localhost:44409</SpaProxyServerUrl>
<SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
<RootNamespace>ajgre_technical_interview</RootNamespace>
Expand All @@ -22,6 +22,10 @@
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
</ItemGroup>

<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
Expand Down
50 changes: 50 additions & 0 deletions API/Controllers/SanctionedEntitiesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using ajgre_technical_interview.Core.Entities;
using ajgre_technical_interview.Core.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace ajgre_technical_interview.API.Controllers
{
[ApiController]
[Route("api/sanctioned-entities")]
public class SanctionedEntitiesController : ControllerBase
{
private readonly ISanctionedEntityRepository _sanctionedEntityRepository;

public SanctionedEntitiesController(ISanctionedEntityRepository repository)
{
_sanctionedEntityRepository = repository;

}

[HttpGet]
public async Task<IActionResult> GetSanctionedEntities()
{
try
{
var entities = await _sanctionedEntityRepository.GetSanctionedEntities();
return Ok(entities);
}
catch (Exception ex)
{
return Problem(ex.Message);
}

}

[HttpPost]
public async Task<ActionResult<SanctionedEntity>> Create(SanctionedEntity entity)
{
if (_sanctionedEntityRepository.Exists(entity.Name, entity.Domicile))
{
return Conflict(new
{
message = $"A sanctioned entity with name '{entity.Name}' and domicile '{entity.Domicile}' already exists."
});
}
var created = await _sanctionedEntityRepository.CreateSanctionedEntity(entity);

return StatusCode(201, created);
}

}
}
21 changes: 19 additions & 2 deletions Program.cs → API/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
using ajgre_technical_interview.Services;

using ajgre_technical_interview.Core.Interfaces;
using ajgre_technical_interview.Infrastructure.Data;

var builder = WebApplication.CreateBuilder(args);


builder.Services.AddCors(opt =>
{
opt.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:4409", "https://localhost:4409");
});
});



// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddSingleton<IDatabaseService, DatabaseService>();
builder.Services.AddSingleton<ISanctionedEntityRepository, SanctionedEntityRepository>();

var app = builder.Build();

Expand All @@ -18,8 +31,12 @@

app.UseHttpsRedirection();
app.UseStaticFiles();


app.UseRouting();

app.UseCors("CorsPolicy");


app.MapControllerRoute(
name: "default",
Expand Down
13 changes: 13 additions & 0 deletions API/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"profiles": {
"API": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
},
"applicationUrl": "https://localhost:65063;http://localhost:65064"
}
}
}
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions ClientApp/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';

import { AppComponent } from './app.component';
import { NavMenuComponent } from './components/nav-menu/nav-menu.component';
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 { SanctionedEntitiesComponent } from './features/sanctioned-entities/sanctioned-entities/sanctioned-entities.component';
import { SanctionedEntitiesModule } from './features/sanctioned-entities/sanctioned-entities.module';


@NgModule({
Expand All @@ -18,13 +18,13 @@ import { JumbotronCounterComponent } from './components/jumbotron-counter/jumbot
NavMenuComponent,
HomeComponent,
CounterComponent,
SanctionedEntitiesComponent,
JumbotronCounterComponent
JumbotronCounterComponent,
],
imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
HttpClientModule,
FormsModule,
SanctionedEntitiesModule,
RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full' },
{ path: 'counter', component: CounterComponent },
Expand Down
3 changes: 1 addition & 2 deletions ClientApp/src/app/app.server.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
import { AppComponent } from './app.component';
import { AppModule } from './app.module';

@NgModule({
imports: [AppModule, ServerModule, ModuleMapLoaderModule],
imports: [AppModule, ServerModule],
bootstrap: [AppComponent]
})
export class AppServerModule { }
4 changes: 1 addition & 3 deletions ClientApp/src/app/components/counter/counter.component.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<h1>Counter</h1>

<p>This is a simple example of an Angular component.</p>

<p aria-live="polite">Current count: <strong>{{ currentCount }}</strong></p>
<p aria-live="polite">Current count: <strong>{{ count$ | async}}</strong></p>

<button class="btn btn-primary" (click)="incrementCounter()">Increment</button>
36 changes: 0 additions & 36 deletions ClientApp/src/app/components/counter/counter.component.spec.ts

This file was deleted.

9 changes: 6 additions & 3 deletions ClientApp/src/app/components/counter/counter.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Component } from '@angular/core';
import { CounterService } from 'src/app/services/counter.service';

@Component({
selector: 'app-counter-component',
templateUrl: './counter.component.html'
})
export class CounterComponent {
public currentCount = 0;
constructor(public counterService: CounterService) { }
count$ = this.counterService.count$;

public incrementCounter() {
this.currentCount++;
incrementCounter() {
this.counterService.incrementCounter();
}

}
3 changes: 1 addition & 2 deletions ClientApp/src/app/components/home/home.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<h1>Hello, world!</h1>
<p>Welcome to the technical interview for the position of Software Engineer at Gallagher Re.</p>
<p>This is a simple ASP.Net Core application with Angular. It includes following tabs:</p>
<ul>
Expand All @@ -25,4 +24,4 @@ <h1>Hello, world!</h1>
</li>
</ul>

<app-jumbotron-counter></app-jumbotron-counter>
<app-jumbotron-counter [count]="count$ | async"></app-jumbotron-counter>
7 changes: 7 additions & 0 deletions ClientApp/src/app/components/home/home.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { CounterService } from 'src/app/services/counter.service';

@Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent {
count$!: Observable<number>;

constructor(private counterService: CounterService) {
this.count$ = this.counterService.count$;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<div class="jumbotron text-center">
<p>Current count:</p>
<p><strong>Please include the counter here</strong></p>
<p aria-live="polite">Current count: <strong>{{count}}</strong></p>
</div>
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';
import { Observable } from 'rxjs';

@Component({
selector: 'app-jumbotron-counter',
templateUrl: './jumbotron-counter.component.html'
})
export class JumbotronCounterComponent {
@Input() count!: number | null;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SanctionedEntitiesComponent } from './sanctioned-entities/sanctioned-entities.component';
import { AddSanctionedEntityComponent } from './sanctioned-entity-form/sanctioned-entity-form.component';
import { ReactiveFormsModule } from '@angular/forms';



@NgModule({
declarations: [
SanctionedEntitiesComponent,
AddSanctionedEntityComponent
],
imports: [
CommonModule,
ReactiveFormsModule
]
})
export class SanctionedEntitiesModule { }
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ <h1 id="tableLabel">Sanctioned Entities</h1>
</tr>
</thead>
<tbody>
<tr *ngFor="let entity of entities">
<tr *ngFor="let entity of entities; trackBy: trackByEntityId">
<td>{{ entity.name }}</td>
<td>{{ entity.domicile }}</td>
<td *ngIf="entity.accepted" class="text-success">Accepted</td>
<td *ngIf="!entity.accepted" class="text-danger">Rejected</td>
</tr>
</tbody>
</table>
<app-sanctioned-entity-form (entityAdded)="onEntityAdded($event)"></app-sanctioned-entity-form>

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Component, OnInit } from '@angular/core';
import { take } from 'rxjs';
import { SanctionedEntity } from 'src/app/models/sanctioned-entity';
import { SanctionedEntitiesService } from 'src/app/services/sanctioned-entities.service';

@Component({
selector: 'app-sanctioned-entities',
templateUrl: './sanctioned-entities.component.html',
styleUrls: ['./sanctioned-entities.component.css']
})
export class SanctionedEntitiesComponent implements OnInit {
public entities: SanctionedEntity[] = [];

constructor(private entitiesService: SanctionedEntitiesService) { }

ngOnInit(): void {
this.loadEntities();
}

loadEntities(): void {
this.entitiesService.getSanctionedEntities().pipe(take(1)).subscribe(entities => {
this.entities = entities;
});
}
onEntityAdded(entity: SanctionedEntity) {
this.entities.push(entity);
}

trackByEntityId(index: number, entity: SanctionedEntity): string {
return entity.id;
}

}
Loading