Skip to content

Commit

Permalink
Task list items
Browse files Browse the repository at this point in the history
  • Loading branch information
davewalker5 committed Mar 12, 2024
1 parent 76e1b68 commit 863255d
Show file tree
Hide file tree
Showing 20 changed files with 238 additions and 37 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The logbook allows for storage and maintenance of the following data:
- Operator details
- Drones, models and manufacturers
- Flights, flight locations and flight properties
- Repair, maintenance and modification records

## Getting Started

Expand Down
4 changes: 2 additions & 2 deletions docker/ui/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:latest
COPY droneflightlog.mvc-1.1.4.0 /opt/droneflightlog.mvc-1.1.4.0
WORKDIR /opt/droneflightlog.mvc-1.1.4.0/bin
COPY droneflightlog.mvc-1.2.0.0 /opt/droneflightlog.mvc-1.2.0.0
WORKDIR /opt/droneflightlog.mvc-1.2.0.0/bin
ENTRYPOINT [ "./DroneFlightLog.Mvc" ]
22 changes: 20 additions & 2 deletions src/DroneFlightLog.Api/Controllers/DronesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,31 @@ public DronesController(IDroneFlightLogFactory<DroneFlightLogDbContext> factory)
_factory = factory;
}

[HttpGet]
[Route("id")]
public async Task<ActionResult<Drone>> GetDroneByIdAsync(int id)
{
Drone drone;

try
{
drone = await _factory.Drones.GetDroneAsync(id);
}
catch (DroneNotFoundException)
{
return NotFound();
}

return drone;
}

[HttpGet]
[Route("")]
public async Task<ActionResult<List<Drone>>> GetDronesAsync()
{
List<Drone> drones = await _factory.Drones.GetDronesAsync(null).ToListAsync();

if (!drones.Any())
if (drones.Count == 0)
{
return NoContent();
}
Expand All @@ -43,7 +61,7 @@ public async Task<ActionResult<List<Drone>>> GetDronesForModelAsync(int modelId)
{
List<Drone> drones = await _factory.Drones.GetDronesAsync(modelId).ToListAsync();

if (!drones.Any())
if (drones.Count == 0)
{
return NoContent();
}
Expand Down
18 changes: 18 additions & 0 deletions src/DroneFlightLog.Api/Controllers/FlightPropertiesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,24 @@ public FlightPropertiesController(IDroneFlightLogFactory<DroneFlightLogDbContext
_factory = factory;
}

[HttpGet]
[Route("{id}")]
public async Task<ActionResult<FlightProperty>> GetPropertyAsync(int id)
{
FlightProperty property;

try
{
property = await _factory.Properties.GetPropertyAsync(id);
}
catch (PropertyNotFoundException)
{
return NotFound();
}

return property;
}

[HttpGet]
[Route("")]
public async Task<ActionResult<List<FlightProperty>>> GetPropertiesAsync()
Expand Down
18 changes: 18 additions & 0 deletions src/DroneFlightLog.Api/Controllers/FlightsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,24 @@ public FlightsController(IDroneFlightLogFactory<DroneFlightLogDbContext> factory
_factory = factory;
}

[HttpGet]
[Route("{id}")]
public async Task<ActionResult<Flight>> GetFlightByIdAsync(int id)
{
Flight flight;

try
{
flight = await _factory.Flights.GetFlightAsync(id);
}
catch (FlightNotFoundException)
{
return NotFound();
}

return flight;
}

[HttpGet]
[Route("{page}/{pageSize}")]
public async Task<ActionResult<List<Flight>>> GetFlightsAsync(int page, int pageSize)
Expand Down
32 changes: 32 additions & 0 deletions src/DroneFlightLog.Data.Tests/FlightPropertyManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,38 @@ public void AddExistingPropertyTest()
_factory.Properties.AddProperty(PropertyName, PropertyType, true);
}

[TestMethod]
public void GetPropertyTest()
{
var property = _factory.Properties.GetProperty(_propertyId);
Assert.AreEqual(PropertyName, property.Name);
Assert.AreEqual(PropertyType, property.DataType);
Assert.IsTrue(property.IsSingleInstance);
}

[TestMethod]
public async Task GetPropertyAsyncTest()
{
var property = await _factory.Properties.GetPropertyAsync(_propertyId);
Assert.AreEqual(PropertyName, property.Name);
Assert.AreEqual(PropertyType, property.DataType);
Assert.IsTrue(property.IsSingleInstance);
}

[TestMethod]
[ExpectedException(typeof(PropertyNotFoundException))]
public void GetPropertyForMissingPropertyTest()
{
_factory.Properties.GetProperty(-1);
}

[TestMethod]
[ExpectedException(typeof(PropertyNotFoundException))]
public async Task GetPropertyForMissingPropertyAsyncTest()
{
await _factory.Properties.GetPropertyAsync(-1);
}

[TestMethod]
public void GetPropertiesTest()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using DroneFlightLog.Data.Entities;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace DroneFlightLog.Data.Binders
{
[ExcludeFromCodeCoverage]
public class MaintenanceRecordTypeJsonConverter : JsonConverter<MaintenanceRecordType>
{
public override MaintenanceRecordType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Expand Down
2 changes: 2 additions & 0 deletions src/DroneFlightLog.Data/Interfaces/IFlightPropertyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface IFlightPropertyManager
Task<FlightProperty> AddPropertyAsync(string name, FlightPropertyDataType type, bool isSingleInstance);
FlightPropertyValue AddPropertyValue(int flightId, int propertyId, object value);
Task<FlightPropertyValue> AddPropertyValueAsync(int flightId, int propertyId, object value);
FlightProperty GetProperty(int propertyId);
Task<FlightProperty> GetPropertyAsync(int propertyId);
IEnumerable<FlightProperty> GetProperties();
IAsyncEnumerable<FlightProperty> GetPropertiesAsync();
IEnumerable<FlightPropertyValue> GetPropertyValues(int flightId);
Expand Down
22 changes: 20 additions & 2 deletions src/DroneFlightLog.Data/Logic/FlightManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@ public async Task<Flight> AddFlightAsync(int operatorId, int droneId, int locati
/// <returns></returns>
public Flight GetFlight(int id)
{
Flight flight = _factory.Context.Flights.FirstOrDefault(f => f.Id == id);
Flight flight = _factory.Context
.Flights
.Include(f => f.Drone)
.ThenInclude(d => d.Model)
.ThenInclude(m => m.Manufacturer)
.Include(f => f.Location)
.Include(f => f.Operator)
.ThenInclude(o => o.Address)
.FirstOrDefault(f => f.Id == id);
ThrowIfFlightNotFound(flight, id);
return flight;
}
Expand All @@ -96,7 +104,15 @@ public Flight GetFlight(int id)
/// <returns></returns>
public async Task<Flight> GetFlightAsync(int id)
{
Flight flight = await _factory.Context.Flights.FirstOrDefaultAsync(f => f.Id == id);
Flight flight = await _factory.Context
.Flights
.Include(f => f.Drone)
.ThenInclude(d => d.Model)
.ThenInclude(m => m.Manufacturer)
.Include(f => f.Location)
.Include(f => f.Operator)
.ThenInclude(o => o.Address)
.FirstOrDefaultAsync(f => f.Id == id);
ThrowIfFlightNotFound(flight, id);
return flight;
}
Expand Down Expand Up @@ -179,6 +195,7 @@ public IEnumerable<Flight> FindFlights(int? operatorId, int? droneId, int? locat
((locationId == null) || (locationId == f.LocationId)) &&
((start == null) || (f.Start >= start)) &&
((end == null) || (f.End <= end)))
.OrderBy(f => f.Start)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);

Expand Down Expand Up @@ -211,6 +228,7 @@ public IAsyncEnumerable<Flight> FindFlightsAsync(int? operatorId, int? droneId,
((locationId == null) || (locationId == f.LocationId)) &&
((start == null) || (f.Start >= start)) &&
((end == null) || (f.End <= end)))
.OrderBy(f => f.Start)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.AsAsyncEnumerable();
Expand Down
24 changes: 24 additions & 0 deletions src/DroneFlightLog.Data/Logic/FlightPropertyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,30 @@ public async Task<FlightPropertyValue> UpdatePropertyValueAsync(int id, object v
return propertyValue;
}

/// <summary>
/// Return a flight propert definition given its Id
/// </summary>
/// <param name="propertyId"></param>
/// <returns></returns>
public FlightProperty GetProperty(int propertyId)
{
FlightProperty property = _context.FlightProperties.FirstOrDefault(p => p.Id == propertyId);
ThrowIfPropertyNotFound(property, propertyId);
return property;
}

/// <summary>
/// Return a flight propert definition given its Id
/// </summary>
/// <param name="propertyId"></param>
/// <returns></returns>
public async Task<FlightProperty> GetPropertyAsync(int propertyId)
{
FlightProperty property = await _context.FlightProperties.FirstOrDefaultAsync(p => p.Id == propertyId);
ThrowIfPropertyNotFound(property, propertyId);
return property;
}

/// <summary>
/// Get all the current property definitions
/// </summary>
Expand Down
8 changes: 4 additions & 4 deletions src/DroneFlightLog.Mvc/Api/DroneClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ public async Task<List<Drone>> GetDronesAsync()
/// <returns></returns>
public async Task<Drone> GetDroneAsync(int id)
{
// TODO : This needs to be replaced with a call to retrieve a single
// drone by Id. For now, retrieve them all then pick the one required
List<Drone> drones = await GetDronesAsync();
Drone drone = drones.First(l => l.Id == id);
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == RouteKey).Route;
string route = $"{baseRoute}/{id}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
Drone drone = JsonConvert.DeserializeObject<Drone>(json);
return drone;
}

Expand Down
8 changes: 2 additions & 6 deletions src/DroneFlightLog.Mvc/Api/FlightClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,10 @@ public FlightClient(HttpClient client, IOptions<AppSettings> settings, IHttpCont
/// <returns></returns>
public async Task<Flight> GetFlightAsync(int flightId)
{
// TODO : This needs to be replaced with a call to retrieve a single flight
// by Id. For now, retrieve an arbitrary large number that will cover them
// all then pick the one required
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == RouteKey).Route;
string route = $"{baseRoute}/1/1000000";
string route = $"{baseRoute}/{flightId}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
List<Flight> flights = JsonConvert.DeserializeObject<List<Flight>>(json);
Flight flight = flights.First(f => f.Id == flightId);
Flight flight = JsonConvert.DeserializeObject<Flight>(json);
return flight;
}

Expand Down
10 changes: 5 additions & 5 deletions src/DroneFlightLog.Mvc/Api/FlightPropertyClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ public async Task<List<FlightProperty>> GetFlightPropertiesAsync()
/// <param name="id"></param>
/// <returns></returns>
public async Task<FlightProperty> GetFlightPropertyAsync(int id)
{
// TODO : This needs to be replaced with a call to retrieve a single
// property by Id. For now, retrieve them all then pick the one required
List<FlightProperty> poperties = await GetFlightPropertiesAsync();
FlightProperty property = poperties.First(l => l.Id == id);
{
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == PropertiesRouteKey).Route;
string route = $"{baseRoute}/{id}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
FlightProperty property = JsonConvert.DeserializeObject<FlightProperty>(json);
return property;
}

Expand Down
9 changes: 4 additions & 5 deletions src/DroneFlightLog.Mvc/Api/LocationClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ public async Task<List<Location>> GetLocationsAsync()
/// <returns></returns>
public async Task<Location> GetLocationAsync(int id)
{
// TODO : This needs to be replaced with a call to retrieve a single
// location by Id. For now, retrieve them all then pick the one
// required
List<Location> locations = await GetLocationsAsync();
Location location = locations.First(l => l.Id == id);
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == RouteKey).Route;
string route = $"{baseRoute}/{id}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
Location location = JsonConvert.DeserializeObject<Location>(json);
return location;
}

Expand Down
35 changes: 33 additions & 2 deletions src/DroneFlightLog.Mvc/Api/MaintenanceRecordClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
namespace DroneFlightLog.Mvc.Api
using DroneFlightLog.Mvc.Configuration;
using DroneFlightLog.Mvc.Entities;
using DroneFlightLog.Mvc.Interfaces;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace DroneFlightLog.Mvc.Api
{
public class MaintenanceRecordClient
public class MaintenanceRecordClient : DroneFlightLogClientBase
{
private const string RouteKey = "MaintenanceRecords";
private const string CacheKey = "MaintenanceRecords";

public MaintenanceRecordClient(HttpClient client, IOptions<AppSettings> settings, IHttpContextAccessor accessor, ICacheWrapper cache)
: base(client, settings, accessor, cache)
{
}

/// <summary>
/// Retrieve a single maintenance record given its ID
/// </summary>
/// <param name="recordId"></param>
/// <returns></returns>
public async Task<MaintenanceRecord> GetMaintenanceRecordAsync(int recordId)
{
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == RouteKey).Route;
string route = $"{baseRoute}/{recordId}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
MaintenanceRecord maintenanceRecord = JsonConvert.DeserializeObject<MaintenanceRecord>(json);
return maintenanceRecord;
}
}
}
9 changes: 4 additions & 5 deletions src/DroneFlightLog.Mvc/Api/ManufacturerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ public async Task<List<Manufacturer>> GetManufacturersAsync()
/// <returns></returns>
public async Task<Manufacturer> GetManufacturerAsync(int id)
{
// TODO : This needs to be replaced with a call to retrieve a single
// manufacturer by Id. For now, retrieve them all then pick the one
// required
List<Manufacturer> manufacturers = await GetManufacturersAsync();
Manufacturer manufacturer = manufacturers.First(m => m.Id == id);
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == RouteKey).Route;
string route = $"{baseRoute}/{id}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
Manufacturer manufacturer = JsonConvert.DeserializeObject<Manufacturer>(json);
return manufacturer;
}

Expand Down
8 changes: 4 additions & 4 deletions src/DroneFlightLog.Mvc/Api/ModelClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ public async Task<List<Model>> GetModelsAsync()
/// <returns></returns>
public async Task<Model> GetModelAsync(int id)
{
// TODO : This needs to be replaced with a call to retrieve a single
// model by Id. For now, retrieve them all then pick the one required
List<Model> models = await GetModelsAsync();
Model model = models.First(m => m.Id == id);
string baseRoute = _settings.Value.ApiRoutes.First(r => r.Name == RouteKey).Route;
string route = $"{baseRoute}/{id}";
string json = await SendDirectAsync(route, null, HttpMethod.Get);
Model model = JsonConvert.DeserializeObject<Model>(json);
return model;
}

Expand Down
Loading

0 comments on commit 863255d

Please sign in to comment.