diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..f2bb5f2 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,12 @@ +# Build +bin/ +obj/ + +# IDE +.vscode + +# MacOS +.DS_Store + +# Generated Data +data.json \ No newline at end of file diff --git a/server/Controllers/CarController.cs b/server/Controllers/CarController.cs new file mode 100644 index 0000000..4df9ab6 --- /dev/null +++ b/server/Controllers/CarController.cs @@ -0,0 +1,157 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Cors; +using System.Collections.Generic; +using System.Linq; +using coding.Models; +using System; +using System.IO; +using Newtonsoft.Json; + +namespace coding.Controllers +{ + [Route("api/[controller]")] + [ApiController] + [EnableCors("MyPolicy")] + public class CarController : ControllerBase + { + private readonly CarContext _context; + private string _path = Path.Combine(Environment.CurrentDirectory, "data.json"); + private void AddCarsToContext(){ + _context.Cars.Add(new Car { Manufacturer = "Ford",Make="Mustang",Model="GT",Year=2015 }); + _context.Cars.Add(new Car { Manufacturer = "Chevrolet",Make="Corvette",Model="Z06",Year=2017 }); + _context.Cars.Add(new Car { Manufacturer = "Dodge",Make="Challenger",Model="Hellcat",Year=2016 }); + _context.SaveChanges(); + } + private void WriteToJSONfile(){ + + try{ + // Create a file to write to. + using (StreamWriter file = System.IO.File.CreateText(_path)) + { + JsonSerializer serializer = new JsonSerializer(); + //saves cars preserving the order (ID) of cars + serializer.Serialize(file, _context.Cars.OrderBy(s => s.Id).ToList()); + } + }catch(Exception e){ + Console.WriteLine("Exception information: {0}", e); + } + } + private List ReadFromJSONfile(){ + try{ + List carsList; + using (StreamReader file = System.IO.File.OpenText(_path)) + { + JsonSerializer serializer = new JsonSerializer(); + carsList = (List)serializer.Deserialize(file, typeof(List)); + } + foreach (Car c in carsList) { + _context.Cars.Add(new Car { Id =c.Id,Manufacturer = c.Manufacturer,Make=c.Make,Model=c.Model,Year=c.Year }); + } + _context.SaveChanges(); + }catch(Exception e){ + Console.WriteLine("Exception information: {0}", e); + //In case ofan exception, 3 cars still wold be added to the _context + // AddCarsToContext(); + } + return _context.Cars.ToList(); + } + + public CarController(CarContext context) + { + _context = context; + + if (_context.Cars.Count() == 0) + { + if (!System.IO.File.Exists(_path)) + { + AddCarsToContext(); + WriteToJSONfile(); + } + else{ + Console.WriteLine("\n\ndata file exist\n\n"); + ReadFromJSONfile(); + } + } + } + //localhost:5000/api/car + //Get all cars + [HttpGet] + public ActionResult> GetAll() + { + WriteToJSONfile(); + //returns the list of cars preserving the order (ID) of cars + return _context.Cars.OrderBy(s => s.Id).ToList(); + } + + //Get one car given the ID + [HttpGet("{id}", Name = "GetCar")] + public ActionResult GetById(long id) + { + var item = _context.Cars.Find(id); + if (item == null) + { + return NotFound(); + } + return item; + } + + //localhost:5000/api/car + //Create Car + [HttpPost] + public IActionResult Create(Car car) + { + if(car.Id == 0){ + car.Id=1; + } + var item = _context.Cars.Find(car.Id); + while(item!=null){ + car.Id = car.Id+1; + item = _context.Cars.Find(car.Id); + } + _context.Cars.Add(car); + _context.SaveChanges(); + WriteToJSONfile(); + return CreatedAtRoute("GetCar", new { id = car.Id }, car); + } + + //localhost:5000/api/car/{id} + //Edit Method + [HttpPut("{id}")] + public IActionResult Update(long id, Car item) + { + var car = _context.Cars.Find(id); + if (car == null) + { + return NotFound(); + } + //send in raw-json body + car.Manufacturer = item.Manufacturer; + car.Make = item.Make; + car.Model = item.Model; + car.Year = item.Year; + + _context.Cars.Update(car); + _context.SaveChanges(); + WriteToJSONfile(); + return NoContent(); + } + //localhost:5000/api/car/{id} + //Delete Method + [HttpDelete("{id}")] + public IActionResult Delete(long id) + { + var car = _context.Cars.Find(id); + if (car == null) + { + return NotFound(); + } + + _context.Cars.Remove(car); + _context.SaveChanges(); + WriteToJSONfile(); + return NoContent(); + } + } + + +} diff --git a/server/Models/Car.cs b/server/Models/Car.cs new file mode 100644 index 0000000..520414d --- /dev/null +++ b/server/Models/Car.cs @@ -0,0 +1,12 @@ +namespace coding.Models +{ + public class Car + { + public long Id { get; set; } + public string Manufacturer { get; set; } + public string Make { get; set; } + public string Model { get; set; } + public int Year { get; set; } + + } +} \ No newline at end of file diff --git a/server/Models/CarContext.cs b/server/Models/CarContext.cs new file mode 100644 index 0000000..b00ef59 --- /dev/null +++ b/server/Models/CarContext.cs @@ -0,0 +1,14 @@ +using Microsoft.EntityFrameworkCore; + +namespace coding.Models +{ + public class CarContext : DbContext + { + public CarContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Cars { get; set; } + } +} \ No newline at end of file diff --git a/server/Program.cs b/server/Program.cs new file mode 100644 index 0000000..5318d22 --- /dev/null +++ b/server/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; + +namespace coding +{ + public class Program + { + public static void Main(string[] args) + { + CreateWebHostBuilder(args).Build().Run(); + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/server/Properties/launchSettings.json b/server/Properties/launchSettings.json new file mode 100644 index 0000000..cacc76f --- /dev/null +++ b/server/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:26620", + "sslPort": 44386 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/car", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "coding": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/car", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/server/Startup.cs b/server/Startup.cs new file mode 100644 index 0000000..1bf0ecf --- /dev/null +++ b/server/Startup.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using coding.Models; + +namespace coding +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddDbContext(opt => + opt.UseInMemoryDatabase("CarsList")); + services.AddMvc() + .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + services.AddCors(o => o.AddPolicy("MyPolicy", builder => + { + builder.AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader(); + })); + } + + public void Configure(IApplicationBuilder app) + { + app.UseDefaultFiles(); + app.UseStaticFiles(); + app.UseMvc(); + app.UseCors("MyPolicy"); + } + } +} \ No newline at end of file diff --git a/server/appsettings.Development.json b/server/appsettings.Development.json new file mode 100644 index 0000000..e203e94 --- /dev/null +++ b/server/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/server/appsettings.json b/server/appsettings.json new file mode 100644 index 0000000..def9159 --- /dev/null +++ b/server/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/server/coding.csproj b/server/coding.csproj new file mode 100644 index 0000000..cf8e03b --- /dev/null +++ b/server/coding.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp2.1 + + + + + + + + + + + + + diff --git a/server/wwwroot/index.html b/server/wwwroot/index.html new file mode 100644 index 0000000..7e82eb5 --- /dev/null +++ b/server/wwwroot/index.html @@ -0,0 +1,76 @@ + + + + + Cars CRUD + + + +

Cars CRUD

+

Add

+
+ + + + + +
+ +
+

Edit

+
+ + + + + + + + +
+
+ +

+ + + + + + + + + + + +
ManufacturerMakeModelYear
+ + + + + \ No newline at end of file diff --git a/server/wwwroot/site.js b/server/wwwroot/site.js new file mode 100644 index 0000000..cdae09b --- /dev/null +++ b/server/wwwroot/site.js @@ -0,0 +1,118 @@ +const uri = 'api/car'; +let cars = null; +function getCount(data) { + const el = $('#counter'); + let name = 'to-do'; + if (data) { + if (data > 1) { + name = 'to-dos'; + } + el.text(data + ' ' + name); + } else { + el.html('No ' + name); + } +} + +$(document).ready(function () { + getData(); +}); + +function getData() { + $.ajax({ + type: 'GET', + url: uri, + success: function (data) { + $('#cars').empty(); + getCount(data.length); + $.each(data, function (key, car) { + // const checked = item.isComplete ? 'checked' : ''; + + $('' + + '' + car.manufacturer + '' + + '' + car.make + '' + + '' + car.model + '' + + '' + car.year + '' + + '' + + '' + + '').appendTo($('#cars')); + }); + + cars = data; + } + }); +} + +function addItem() { + const car = { + 'manufacturer': $('#add-manufacturer').val(), + 'make': $('#add-make').val(), + 'model': $('#add-model').val(), + 'year': $('#add-year').val(), + }; + + $.ajax({ + type: 'POST', + accepts: 'application/json', + url: uri, + contentType: 'application/json', + data: JSON.stringify(car), + error: function (jqXHR, textStatus, errorThrown) { + alert('here'); + }, + success: function (result) { + getData(); + $('#add-manufacturer').val(''); + } + }); +} + +function deleteItem(id) { + $.ajax({ + url: uri + '/' + id, + type: 'DELETE', + success: function (result) { + getData(); + } + }); +} + +function editItem(id) { + $.each(cars, function (key, car) { + if (car.id === id) { + $('#edit-manufacturer').val(car.manufacturer); + $('#edit-make').val(car.make); + $('#edit-model').val(car.model); + $('#edit-year').val(car.year); + $('#edit-id').val(car.id); + } + }); + $('#spoiler').css({ 'display': 'block' }); +} + +$('.my-form').on('submit', function () { + const car = { + 'manufacturer': $('#edit-manufacturer').val(), + 'make': $('#edit-make').val(), + 'model': $('#edit-model').val(), + 'year': $('#edit-year').val(), + 'id': $('#edit-id').val() + }; + + $.ajax({ + url: uri + '/' + $('#edit-id').val(), + type: 'PUT', + accepts: 'application/json', + contentType: 'application/json', + data: JSON.stringify(car), + success: function (result) { + getData(); + } + }); + + closeInput(); + return false; +}); + +function closeInput() { + $('#spoiler').css({ 'display': 'none' }); +} \ No newline at end of file