Finished api

This commit is contained in:
didier amyot committed 2023-09-18 10:08:16 -04:00
1 parent 3cf5a889a7
commit 7ff304dadf
9 files changed
+216 -7

No files matched your search

+1
View File
@@ -132,3 +132,4 @@ $RECYCLE.BIN/
_NCrunch* _NCrunch*
.vscode
@@ -0,0 +1,25 @@
namespace RobotsWantedLeague.Test.Services;
using RobotsWantedLeague.Models;
using RobotsWantedLeague.Services;
[TestClass]
public class NotEmptyRobotsServiceTest
{
[TestMethod]
public void TestHappyPath()
{
IRobotsService service = new NotEmptyRobotsService();
Assert.AreEqual(3, service.Robots.Count);
Robot robot = service.CreateRobot("paul", 2, 3, "canada");
Assert.AreEqual(robot.Name, "paul");
Assert.AreEqual(robot.Weight, 2);
Assert.AreEqual(4, service.Robots.Count);
service.DeleteRobotById(robot.Id);
Assert.AreEqual(3, service.Robots.Count);
}
}
@@ -5,6 +5,14 @@ using RobotsWantedLeague.Services;
namespace RobotsWantedLeague.Controllers; namespace RobotsWantedLeague.Controllers;
public class RobotRequest{
public string Name { get; set; }
public int Height { get; set; }
public int Weight { get; set; }
public string Country { get; set; }
}
public class RobotsController : Controller public class RobotsController : Controller
{ {
private readonly ILogger<RobotsController> _logger; private readonly ILogger<RobotsController> _logger;
@@ -22,14 +30,26 @@ public class RobotsController : Controller
return View(robotsService.Robots); return View(robotsService.Robots);
} }
public IActionResult Privacy() public IActionResult Robot(int id){
{ Robot robot = robotsService.GetRobotById(id);
return View(robot);
}
[HttpGet]
public IActionResult CreateRobot(){
return View(); return View();
} }
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [HttpPost]
public IActionResult Error() public IActionResult CreateRobot([FromBody] RobotRequest robot)
{ {
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); Robot r = robotsService.CreateRobot(robot.Name,
robot.Weight,
robot.Height,
robot.Country);
string htmxRedirectHeaderName = "HX-Redirect";
string redirectURL = "/robots/robot?id=" + r.Id;
Response.Headers.Add(htmxRedirectHeaderName, redirectURL);
return Ok();
} }
} }
+1 -1
View File
@@ -4,7 +4,7 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
builder.Services.AddSingleton<IRobotsService, RobotsService>(); builder.Services.AddSingleton<IRobotsService, NotEmptyRobotsService>();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
@@ -0,0 +1,35 @@
namespace RobotsWantedLeague.Services;
using RobotsWantedLeague.Models;
public class NotEmptyRobotsService: IRobotsService
{
private readonly IRobotsService underlyingRobotsService;
public List<Robot> Robots { get => underlyingRobotsService.Robots; }
public NotEmptyRobotsService()
{
this.underlyingRobotsService = new RobotsService();
this.underlyingRobotsService.CreateRobot("Alice", 1050, 2, "Bhutan");
this.underlyingRobotsService.CreateRobot("Bob", 5001, 5, "Vanuatu");
this.underlyingRobotsService.CreateRobot("Xu", 890, 1, "Taiwan");
}
public Robot CreateRobot(string name,
int weight,
int height,
string country)
{
return underlyingRobotsService.CreateRobot(name, weight, height, country);
}
public Robot? GetRobotById(int id){
return underlyingRobotsService.GetRobotById(id);
}
public bool DeleteRobotById(int id){
return underlyingRobotsService.DeleteRobotById(id);
}
}
@@ -0,0 +1,43 @@
<form hx-post="/robots/createRobot"
hx-ext="json-enc"
hx-trigger="submit">
<div class="form-group">
<label for="name">Le nom du robot</label>
<input type="text"
class="form-control"
id="name"
name="name"
placeholder="Le Géant Ferré">
</div>
<div class="form-group">
<label for="weight">Poids (kg)</label>
<input type="number"
class="form-control"
id="weight"
name="weight"
min="0"
placeholder="87">
</div>
<div class="form-group">
<label for="height">Taille (m)</label>
<input type="number"
class="form-control"
id="height"
name="height"
min="0"
placeholder="2">
</div>
<div class="form-group">
<label for="country">Pays</label>
<input type="text"
class="form-control"
id="country"
name="country"
placeholder="Suriname">
</div>
<button type="submit" class="btn btn-primary mt-3">Submit</button>
</form>
@@ -11,3 +11,6 @@
</li> </li>
} }
</ul> </ul>
<a class="btn btn-primary mt-2" href="/robots/createRobot"> Ajouter un robot</a>
@@ -0,0 +1,29 @@
@model Robot
<div class="container">
<div class="d-flex justify-content-center">
<div class="card" style="width: 10rem;">
<img class="card-img-top"
src="https://robohash.org/aligator@Model.Id?set=set2">
</div>
</div>
</div>
<table class="table">
<tr>
<th>Nom</th><td>@Model.Name</td>
</tr>
<tr>
<th>Poids</th><td>@Model.Weight (kg)</td>
</tr>
<tr>
<th>Taille</th><td>@Model.Height (m)</td>
</tr>
<tr>
<th>Pays</th><td>@Model.Country</td>
</tr>
</table>
+54 -1
View File
@@ -7,12 +7,65 @@
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /> <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/RobotsWantedLeague.styles.css" asp-append-version="true" /> <link rel="stylesheet" href="~/RobotsWantedLeague.styles.css" asp-append-version="true" />
<script src="https://unpkg.com/htmx.org@1.9.5"`
integrity="sha384-xcuj3WpfgjlKF+FXhSQFQ0ZNr39ln+hwjN3npfM9VBnUskLolQAcN80McRIVOPuO"
crossorigin="anonymous"></script>
<script>
(function () {
function _isNumeric(str) {
if (typeof str != "string") {
return false
}
return !isNaN(str) && !isNaN(parseFloat(str));
}
function _cast(str) {
return _isNumeric(str) ? parseFloat(str) : str;
}
function _addAssocToDict(obj, key, value) {
let splittedKey = Array.isArray(key) ? key : key.split(".");
const keyToAdd = splittedKey.shift();
const isTerminal = splittedKey.length === 0;
if (isTerminal) {
obj[keyToAdd] = _cast(value);
return obj;
}
if (!(keyToAdd in obj)) {
obj[keyToAdd] = {};
}
return _addAssocToDict(obj[keyToAdd], splittedKey, value);
}
function _createPayload(params) {
let ret = {};
for (let key of Object.keys(params)) {
_addAssocToDict(ret, key, params[key]);
}
return ret;
}
htmx.defineExtension('json-enc', {
onEvent: function (name, evt) {
if (name === "htmx:configRequest") {
evt.detail.headers['Content-Type'] = "application/json";
}
},
encodeParameters: function (xhr, parameters, elt) {
xhr.overrideMimeType('text/json');
return (JSON.stringify(_createPayload(parameters)));
}
});
})();
</script>
</head> </head>
<body> <body>
<header> <header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"> <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">RobotsWantedLeague</a> <a class="navbar-brand" href="/">RobotsWantedLeague</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent" <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation"> aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>