diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Controllers/ImagesController.cs b/Src/Clients/PaintedProsthetics.Web.Api/Controllers/ImagesController.cs new file mode 100644 index 0000000..f418b74 --- /dev/null +++ b/Src/Clients/PaintedProsthetics.Web.Api/Controllers/ImagesController.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using PaintedProsthetics.Gallery.Models; +using PaintedProsthetics.Web.Api.Helpers; + +namespace PaintedProsthetics.Web.Api.Controllers +{ + [Route("api/Images")] + [ApiController] + public class ImagesController : ControllerBase + { + private readonly ImagesContext _context; + + public ImagesController(ImagesContext context) + { + _context = context; + } + + // GET: api/Images + [HttpGet] + public async Task>> GetImages() + { + return await _context.Images.ToListAsync(); + } + + // GET: api/Images/5 + [HttpGet("{id}")] + public async Task> GetImage(long id) + { + var image = await _context.Images.FindAsync(id); + + if (image == null) + { + return NotFound(); + } + + return image; + } + + // PUT: api/Images/5 + // To protect from overposting attacks, enable the specific properties you want to bind to, for + // more details, see https://go.microsoft.com/fwlink/?linkid=2123754. + [HttpPut("{id}")] + public async Task PutImage(long id, Image image) + { + if (id != image.Id) + { + return BadRequest(); + } + + _context.Entry(image).State = EntityState.Modified; + + try + { + await _context.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (!ImageExists(id)) + { + return NotFound(); + } + else + { + throw; + } + } + + return NoContent(); + } + + // POST: api/Images + // To protect from overposting attacks, enable the specific properties you want to bind to, for + // more details, see https://go.microsoft.com/fwlink/?linkid=2123754. + [HttpPost] + public async Task> PostImage(Image image) + { + _context.Images.Add(image); + await _context.SaveChangesAsync(); + + //return CreatedAtAction("GetImage", new { id = image.Id }, image); + return CreatedAtAction(nameof(GetImage), new { id = image.Id }, image); + } + + // DELETE: api/Images/5 + [HttpDelete("{id}")] + public async Task> DeleteImage(long id) + { + var image = await _context.Images.FindAsync(id); + if (image == null) + { + return NotFound(); + } + + _context.Images.Remove(image); + await _context.SaveChangesAsync(); + + return image; + } + + private bool ImageExists(long id) + { + return _context.Images.Any(e => e.Id == id); + } + } +} diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Helpers/ImagesContext.cs b/Src/Clients/PaintedProsthetics.Web.Api/Helpers/ImagesContext.cs new file mode 100644 index 0000000..eacbf06 --- /dev/null +++ b/Src/Clients/PaintedProsthetics.Web.Api/Helpers/ImagesContext.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using PaintedProsthetics.Gallery.Models; + +namespace PaintedProsthetics.Web.Api.Helpers +{ + public class ImagesContext : DbContext + { + public ImagesContext(DbContextOptions options) : base(options) + { + + } + + public DbSet Images { get; set; } + } +} diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Migrations/20200912040458_InitialCreate.Designer.cs b/Src/Clients/PaintedProsthetics.Web.Api/Migrations/20200912040458_InitialCreate.Designer.cs new file mode 100644 index 0000000..fc8fe5d --- /dev/null +++ b/Src/Clients/PaintedProsthetics.Web.Api/Migrations/20200912040458_InitialCreate.Designer.cs @@ -0,0 +1,45 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PaintedProsthetics.Web.Api.Helpers; + +namespace PaintedProsthetics.Web.Api.Migrations +{ + [DbContext(typeof(ImagesContext))] + [Migration("20200912040458_InitialCreate")] + partial class InitialCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.8"); + + modelBuilder.Entity("PaintedProsthetics.Gallery.Models.Image", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AltText") + .HasColumnType("TEXT"); + + b.Property("Artist") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Images"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Migrations/20200912040458_InitialCreate.cs b/Src/Clients/PaintedProsthetics.Web.Api/Migrations/20200912040458_InitialCreate.cs new file mode 100644 index 0000000..c9c4d97 --- /dev/null +++ b/Src/Clients/PaintedProsthetics.Web.Api/Migrations/20200912040458_InitialCreate.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace PaintedProsthetics.Web.Api.Migrations +{ + public partial class InitialCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Images", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Title = table.Column(nullable: true), + AltText = table.Column(nullable: true), + ImageUrl = table.Column(nullable: true), + Artist = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Images", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Images"); + } + } +} diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Migrations/ImagesContextModelSnapshot.cs b/Src/Clients/PaintedProsthetics.Web.Api/Migrations/ImagesContextModelSnapshot.cs new file mode 100644 index 0000000..93b8aa3 --- /dev/null +++ b/Src/Clients/PaintedProsthetics.Web.Api/Migrations/ImagesContextModelSnapshot.cs @@ -0,0 +1,43 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PaintedProsthetics.Web.Api.Helpers; + +namespace PaintedProsthetics.Web.Api.Migrations +{ + [DbContext(typeof(ImagesContext))] + partial class ImagesContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.8"); + + modelBuilder.Entity("PaintedProsthetics.Gallery.Models.Image", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AltText") + .HasColumnType("TEXT"); + + b.Property("Artist") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Images"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Src/Clients/PaintedProsthetics.Web.Api/PaintedProsthetics.Web.Api.csproj b/Src/Clients/PaintedProsthetics.Web.Api/PaintedProsthetics.Web.Api.csproj index 1bb254f..8cab5eb 100644 --- a/Src/Clients/PaintedProsthetics.Web.Api/PaintedProsthetics.Web.Api.csproj +++ b/Src/Clients/PaintedProsthetics.Web.Api/PaintedProsthetics.Web.Api.csproj @@ -4,6 +4,22 @@ netcoreapp3.1 + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + @@ -18,5 +34,9 @@ + + + + diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Properties/launchSettings.json b/Src/Clients/PaintedProsthetics.Web.Api/Properties/launchSettings.json index 5590205..577f193 100644 --- a/Src/Clients/PaintedProsthetics.Web.Api/Properties/launchSettings.json +++ b/Src/Clients/PaintedProsthetics.Web.Api/Properties/launchSettings.json @@ -20,8 +20,8 @@ "PaintedProsthetics.Web.Api": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "weatherforecast", - "applicationUrl": "https://localhost:5001;http://localhost:5000", + "launchUrl": "api/Images", + "applicationUrl": "https://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/Src/Clients/PaintedProsthetics.Web.Api/Startup.cs b/Src/Clients/PaintedProsthetics.Web.Api/Startup.cs index c617a04..00ca40b 100644 --- a/Src/Clients/PaintedProsthetics.Web.Api/Startup.cs +++ b/Src/Clients/PaintedProsthetics.Web.Api/Startup.cs @@ -3,6 +3,11 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.EntityFrameworkCore; +using PaintedProsthetics.Web.Api.Helpers; +using PaintedProsthetics.Web.Api.Controllers; +using Microsoft.AspNetCore.Cors; +using System.Web.Http; namespace PaintedProsthetics.Web.Api { @@ -13,11 +18,24 @@ public Startup(IConfiguration configuration) Configuration = configuration; } + public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + services.AddDbContext(opt => + opt.UseSqlServer(Configuration.GetConnectionString("ImagesContext"))); + + services.AddCors(options => + { + options.AddDefaultPolicy( + builder => + { + builder.WithOrigins("http://localhost:3000").AllowAnyHeader(); + }); + }); + services.AddControllers(); } @@ -32,6 +50,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseHttpsRedirection(); app.UseRouting(); + + app.UseCors(); app.UseAuthorization(); diff --git a/Src/Clients/PaintedProsthetics.Web.Api/appsettings.json b/Src/Clients/PaintedProsthetics.Web.Api/appsettings.json index d9d9a9b..513df4d 100644 --- a/Src/Clients/PaintedProsthetics.Web.Api/appsettings.json +++ b/Src/Clients/PaintedProsthetics.Web.Api/appsettings.json @@ -6,5 +6,8 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" -} + "AllowedHosts": "*", + "ConnectionStrings": { + "ImagesContext": "Server=(localdb)\\mssqllocaldb;Database=ImagesContext-6f3de508-a343-4969-976c-1df4bc0604d5;Trusted_Connection=True;MultipleActiveResultSets=true" + } +} \ No newline at end of file diff --git a/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/Helpers/config.js b/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/Helpers/config.js new file mode 100644 index 0000000..fa04b7b --- /dev/null +++ b/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/Helpers/config.js @@ -0,0 +1,3 @@ +export const config = { + apiUrl: 'https://localhost:5001' +}; \ No newline at end of file diff --git a/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/components/Image-Gallery/Image-Gallery.js b/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/components/Image-Gallery/Image-Gallery.js index 9d2c572..ed09b46 100644 --- a/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/components/Image-Gallery/Image-Gallery.js +++ b/Src/Clients/PaintedProsthetics.Web.Client/ClientApp/src/components/Image-Gallery/Image-Gallery.js @@ -2,15 +2,31 @@ import * as React from "react"; import "./carousel.css"; import { Carousel } from "react-responsive-carousel"; import images from "./GalleryImages"; +import { config } from "../../Helpers/config" export default class ImageGallery extends React.Component { constructor(props) { super(props); this.state = { - images : images, + images : [], clicked: true } } + + componentDidMount() + { + fetch(config.apiUrl + "/api/Images", + { + method: 'GET' + }) + .then(res => res.json()) + .then((data) => + { + this.setState({ images: data }); + { console.log(data) } + }) + .catch(console.log) + } onClickItemEvent() { this.setState({ clicked: !this.state.clicked }); @@ -23,9 +39,9 @@ export default class ImageGallery extends React.Component { const images_list = this.state.images.map( (element) => { return ( -
- -

{element.Title}

+
+ +

{element.title}

); }); diff --git a/Src/Clients/PaintedProsthetics.Web.Client/PaintedProsthetics.Web.Client.csproj b/Src/Clients/PaintedProsthetics.Web.Client/PaintedProsthetics.Web.Client.csproj index 5a7d6a1..3601d43 100644 --- a/Src/Clients/PaintedProsthetics.Web.Client/PaintedProsthetics.Web.Client.csproj +++ b/Src/Clients/PaintedProsthetics.Web.Client/PaintedProsthetics.Web.Client.csproj @@ -7,9 +7,12 @@ false ClientApp\ $(DefaultItemExcludes);$(SpaRoot)node_modules\** + PaintedProsthetics.Web.Client.Program + + @@ -34,6 +37,7 @@ + diff --git a/Src/Clients/PaintedProsthetics.Web.Client/Properties/launchSettings.json b/Src/Clients/PaintedProsthetics.Web.Client/Properties/launchSettings.json index 3edfcdd..690ed4d 100644 --- a/Src/Clients/PaintedProsthetics.Web.Client/Properties/launchSettings.json +++ b/Src/Clients/PaintedProsthetics.Web.Client/Properties/launchSettings.json @@ -18,7 +18,7 @@ "PaintedProsthetics.Web.Client": { "commandName": "Project", "launchBrowser": true, - "applicationUrl": "https://localhost:5001;http://localhost:5000", + "applicationUrl": "https://localhost:5002;http://localhost:5003", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/Src/Clients/PaintedProsthetics.Web.Client/Startup.cs b/Src/Clients/PaintedProsthetics.Web.Client/Startup.cs index d73b33d..4a4a5c8 100644 --- a/Src/Clients/PaintedProsthetics.Web.Client/Startup.cs +++ b/Src/Clients/PaintedProsthetics.Web.Client/Startup.cs @@ -1,9 +1,13 @@ using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using PaintedProsthetics.Web.Api.Helpers; +using System.Web.Http; namespace PaintedProsthetics.Web.Client { @@ -19,6 +23,9 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + services.AddDbContext(opt => + opt.UseSqlServer(Configuration.GetConnectionString("ImagesContext"))); + services.AddControllersWithViews(); // In production, the React files will be served from this directory diff --git a/Src/Clients/PaintedProsthetics.Web.Client/appsettings.json b/Src/Clients/PaintedProsthetics.Web.Client/appsettings.json index d9d9a9b..8a9c639 100644 --- a/Src/Clients/PaintedProsthetics.Web.Client/appsettings.json +++ b/Src/Clients/PaintedProsthetics.Web.Client/appsettings.json @@ -6,5 +6,8 @@ "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "ImagesContext": "Server=(localdb)\\mssqllocaldb;Database=ImagesContext-6f3de508-a343-4969-976c-1df4bc0604d5;Trusted_Connection=True;MultipleActiveResultSets=true" + } } diff --git a/Src/Domain/PaintedProsthetics.Gallery/Models/Image.cs b/Src/Domain/PaintedProsthetics.Gallery/Models/Image.cs new file mode 100644 index 0000000..b6a354a --- /dev/null +++ b/Src/Domain/PaintedProsthetics.Gallery/Models/Image.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace PaintedProsthetics.Gallery.Models +{ + public class Image + { + public int Id { get; set; } + public string Title { get; set; } + public string AltText { get; set; } + public string ImageUrl { get; set; } + public string Artist { get; set; } + } +} diff --git a/Src/Domain/PaintedProsthetics.Gallery/PaintedProsthetics.Gallery.csproj b/Src/Domain/PaintedProsthetics.Gallery/PaintedProsthetics.Gallery.csproj index f31ef82..bfb582f 100644 --- a/Src/Domain/PaintedProsthetics.Gallery/PaintedProsthetics.Gallery.csproj +++ b/Src/Domain/PaintedProsthetics.Gallery/PaintedProsthetics.Gallery.csproj @@ -5,7 +5,6 @@ -