From 0f28e18ed2b4d9ae7efb0cacd169fb38de4a2142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zieli=C5=84ski?= Date: Wed, 21 Dec 2022 18:35:26 +0100 Subject: [PATCH] Save DataSet --- .../login-page/login-page.component.scss | 17 ++ Frontend/src/app/models/dataSet.model.ts | 32 +-- .../data-set-edit/data-set-edit.component.ts | 11 +- .../data-sets-list.component.html | 7 +- .../data-sets-list.component.ts | 2 +- WebAPI/Controllers/AuthController.cs | 2 +- WebAPI/Controllers/DataSetsController.cs | 50 +++++ ...21221165749_DataSetIdOnDataRow.Designer.cs | 199 ++++++++++++++++++ .../20221221165749_DataSetIdOnDataRow.cs | 60 ++++++ .../Migrations/AppDbContextModelSnapshot.cs | 6 +- WebAPI/Models/DataRow.cs | 1 + WebAPI/Program.cs | 10 +- WebAPI/dataParsers/csv.parser.cs | 2 + 13 files changed, 359 insertions(+), 40 deletions(-) create mode 100644 WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.Designer.cs create mode 100644 WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.cs diff --git a/Frontend/src/app/components/login-page/login-page.component.scss b/Frontend/src/app/components/login-page/login-page.component.scss index 3b4205f..52efa04 100644 --- a/Frontend/src/app/components/login-page/login-page.component.scss +++ b/Frontend/src/app/components/login-page/login-page.component.scss @@ -34,6 +34,23 @@ mat-form-field { .load { text-align: center; } +.loading-container { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + background-color: rgba(100, 100, 100, 0.3); + z-index: 1400; + } + .loading-img { + position: absolute; + margin: auto; + top: 0; + left: 0; + right: 0; + bottom: 0; + } /* for mobile */ @media screen and (max-width: 700px) { .container { diff --git a/Frontend/src/app/models/dataSet.model.ts b/Frontend/src/app/models/dataSet.model.ts index 8b1cabb..65417ed 100644 --- a/Frontend/src/app/models/dataSet.model.ts +++ b/Frontend/src/app/models/dataSet.model.ts @@ -19,6 +19,10 @@ export class DataSet extends Base { Object.assign(this, Object.assign(this, super.deserialize(input))); return this; } + override serialize() { + this.number = 0; // will be overrided in backend + return Object.assign({}, this); + } static getForm(fb: UntypedFormBuilder) { return fb.group({ id: [null], @@ -44,27 +48,16 @@ export class DataSet extends Base { this.createdBy = undefined; this.modifiedBy = undefined; } - //API Actions - /* - static add(input: Account, _http: HttpClient, _data: DataService): Promise { + //API Actions + static add(input: DataSet, _http: HttpClient): Promise { return new Promise((resolve, reject) => { - _http.post(`${environment.api.url}/accounts`, {...input.serialize(), modifiedById: _data.currentUser.id }).subscribe({ + _http.post(`${environment.api.url}/datasets`, {...input.serialize(), }).subscribe({ next: (data) => resolve(data), error: (e) => reject(e) } ); }); } - static update(input: Account, _http: HttpClient, _data: DataService): Promise { - return new Promise((resolve, reject) => { - _http.patch(`${environment.api.url}/accounts`, {...input.serialize(), modifiedById: _data.currentUser.id }).subscribe({ - next: (data) => resolve(data), - error: (e) => reject(e) - } - ); - }); - } - */ static getList(_http: HttpClient): any { return new Promise((resolve, reject) => { _http.get(`${environment.api.url}/datasets`) @@ -75,7 +68,6 @@ export class DataSet extends Base { }) }); } - static getById(id: string, _http: HttpClient): Promise { return new Promise((resolve, reject) => { _http.get(`${environment.api.url}/datasets/${id}`).pipe(map(x => new DataSet().deserialize(x))).subscribe({ @@ -98,14 +90,4 @@ export class DataSet extends Base { }) }) } - /* - static delete(id: string, _http: HttpClient): Promise { - return new Promise((resolve, reject)=> { - _http.delete(`${environment.api.url}/accounts/${id}`).subscribe({ - next: (data) => resolve(data), - error: (e) => reject(e) - }) - }); - } - */ } \ No newline at end of file diff --git a/Frontend/src/app/modules/data-sets/data-set-edit/data-set-edit.component.ts b/Frontend/src/app/modules/data-sets/data-set-edit/data-set-edit.component.ts index c078102..fc2ca18 100644 --- a/Frontend/src/app/modules/data-sets/data-set-edit/data-set-edit.component.ts +++ b/Frontend/src/app/modules/data-sets/data-set-edit/data-set-edit.component.ts @@ -59,16 +59,9 @@ export class DataSetEditComponent implements OnInit { if (this.form.invalid) { return; } - /* this.document.loadForm(this.form); - let id; - if (this.route$.snapshot.paramMap.get('id') === 'new') { - id = await DataSet.add(this.document, this.http$, this._data); - } else { - id = await DataSet.update(this.document, this._http, this._data); - } - this._router.navigate(['../../Detail', id], { relativeTo: this._route}); - */ + const id = await DataSet.add(this.document, this.http$); + // this._router.navigate(['../../Detail', id], { relativeTo: this._route}); } generateNumber() { this.form.patchValue({ diff --git a/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.html b/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.html index 329b54a..5a51bc7 100644 --- a/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.html +++ b/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.html @@ -23,9 +23,14 @@ - Źródło + Nazwa {{item.name}} + + + Źródło + {{item.source}} + diff --git a/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.ts b/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.ts index a58b40c..8178d50 100644 --- a/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.ts +++ b/Frontend/src/app/modules/data-sets/data-sets-list/data-sets-list.component.ts @@ -11,7 +11,7 @@ import { DataSet } from 'src/app/models/dataSet.model'; styleUrls: ['./data-sets-list.component.scss'] }) export class DataSetsListComponent implements OnInit { - displayedColumns = ['number', 'name']; + displayedColumns = ['number', 'name', 'source']; dataSource!: MatTableDataSource; @ViewChild(MatPaginator) paginator!: MatPaginator; diff --git a/WebAPI/Controllers/AuthController.cs b/WebAPI/Controllers/AuthController.cs index 0e06fbd..c53103c 100644 --- a/WebAPI/Controllers/AuthController.cs +++ b/WebAPI/Controllers/AuthController.cs @@ -53,7 +53,7 @@ namespace WebAPI.Controllers Subject = new ClaimsIdentity(new[] { new Claim("Id", Guid.NewGuid().ToString()), - new Claim(JwtRegisteredClaimNames.Sub, user.UserName), + new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }), diff --git a/WebAPI/Controllers/DataSetsController.cs b/WebAPI/Controllers/DataSetsController.cs index 100d029..8c5fac6 100644 --- a/WebAPI/Controllers/DataSetsController.cs +++ b/WebAPI/Controllers/DataSetsController.cs @@ -35,6 +35,19 @@ namespace WebAPI.Controllers } } [HttpPost] + public IActionResult Save(DataSet input) + { + try + { + Request.Headers.TryGetValue("userId", out var value); + Guid currentUserId = new Guid(value); + return Ok(AddDataSet(input, currentUserId).Id); + } catch(Exception e) + { + return BadRequest(e.ToString()); + } + } + [HttpPost] [DisableRequestSizeLimit] [Route("parseFile")] public IActionResult ParseFile() @@ -42,5 +55,42 @@ namespace WebAPI.Controllers var parser = new csvParser(); return Ok(parser.parse(Request.Form.Files[0])); } + + // + private DataSet AddDataSet(DataSet input, Guid currentUserId) + { + input.Number = db.DataSets.Count() + 1; + input.CreatedById = currentUserId; + input.ModifiedById = currentUserId; + input.CreatedAt = DateTime.UtcNow; + input.ModifiedAt = DateTime.UtcNow; + + db.DataSets.Add(input); + SaveDataRows(input.Id, input.DataRows, currentUserId); + db.SaveChanges(); + return input; + } + + private void SaveDataRows(Guid id, ICollection dataRows, Guid currentUserId) + { + try + { + List ids = new List(); + foreach (Models.DataRow dataRow in dataRows) + { + dataRow.CreatedById = currentUserId; + dataRow.CreatedAt = DateTime.UtcNow; + dataRow.ModifiedById = currentUserId; + dataRow.ModifiedAt = DateTime.UtcNow; + dataRow.DataSetId= id; + + db.DataRows.Add(dataRow); + } + } + catch (Exception) + { + throw; + } + } } } \ No newline at end of file diff --git a/WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.Designer.cs b/WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.Designer.cs new file mode 100644 index 0000000..e583ddf --- /dev/null +++ b/WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.Designer.cs @@ -0,0 +1,199 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using WebAPI; + +#nullable disable + +namespace WebAPI.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20221221165749_DataSetIdOnDataRow")] + partial class DataSetIdOnDataRow + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("WebAPI.Models.DataRow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedById") + .HasColumnType("uniqueidentifier"); + + b.Property("DataSetId") + .HasColumnType("uniqueidentifier"); + + b.Property("Desc1") + .HasColumnType("nvarchar(max)"); + + b.Property("Desc2") + .HasColumnType("nvarchar(max)"); + + b.Property("Desc3") + .HasColumnType("nvarchar(max)"); + + b.Property("Desc4") + .HasColumnType("nvarchar(max)"); + + b.Property("Desc5") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("ModifiedAt") + .HasColumnType("datetime2"); + + b.Property("ModifiedById") + .HasColumnType("uniqueidentifier"); + + b.Property("Value") + .HasColumnType("real"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DataSetId"); + + b.HasIndex("ModifiedById"); + + b.ToTable("DataRows"); + }); + + modelBuilder.Entity("WebAPI.Models.DataSet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("CreatedById") + .HasColumnType("uniqueidentifier"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("ModifiedAt") + .HasColumnType("datetime2"); + + b.Property("ModifiedById") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Number") + .IsRequired() + .HasColumnType("int"); + + b.Property("Source") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedById"); + + b.HasIndex("ModifiedById"); + + b.ToTable("DataSets"); + }); + + modelBuilder.Entity("WebAPI.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAt") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("UserName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("WebAPI.Models.DataRow", b => + { + b.HasOne("WebAPI.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WebAPI.Models.DataSet", null) + .WithMany("DataRows") + .HasForeignKey("DataSetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WebAPI.Models.User", "ModifiedBy") + .WithMany() + .HasForeignKey("ModifiedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("ModifiedBy"); + }); + + modelBuilder.Entity("WebAPI.Models.DataSet", b => + { + b.HasOne("WebAPI.Models.User", "CreatedBy") + .WithMany() + .HasForeignKey("CreatedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WebAPI.Models.User", "ModifiedBy") + .WithMany() + .HasForeignKey("ModifiedById") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CreatedBy"); + + b.Navigation("ModifiedBy"); + }); + + modelBuilder.Entity("WebAPI.Models.DataSet", b => + { + b.Navigation("DataRows"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.cs b/WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.cs new file mode 100644 index 0000000..6f4d998 --- /dev/null +++ b/WebAPI/Migrations/20221221165749_DataSetIdOnDataRow.cs @@ -0,0 +1,60 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WebAPI.Migrations +{ + /// + public partial class DataSetIdOnDataRow : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_DataRows_DataSets_DataSetId", + table: "DataRows"); + + migrationBuilder.AlterColumn( + name: "DataSetId", + table: "DataRows", + type: "uniqueidentifier", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000"), + oldClrType: typeof(Guid), + oldType: "uniqueidentifier", + oldNullable: true); + + migrationBuilder.AddForeignKey( + name: "FK_DataRows_DataSets_DataSetId", + table: "DataRows", + column: "DataSetId", + principalTable: "DataSets", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_DataRows_DataSets_DataSetId", + table: "DataRows"); + + migrationBuilder.AlterColumn( + name: "DataSetId", + table: "DataRows", + type: "uniqueidentifier", + nullable: true, + oldClrType: typeof(Guid), + oldType: "uniqueidentifier"); + + migrationBuilder.AddForeignKey( + name: "FK_DataRows_DataSets_DataSetId", + table: "DataRows", + column: "DataSetId", + principalTable: "DataSets", + principalColumn: "Id"); + } + } +} diff --git a/WebAPI/Migrations/AppDbContextModelSnapshot.cs b/WebAPI/Migrations/AppDbContextModelSnapshot.cs index 43e1acb..e177aae 100644 --- a/WebAPI/Migrations/AppDbContextModelSnapshot.cs +++ b/WebAPI/Migrations/AppDbContextModelSnapshot.cs @@ -38,7 +38,7 @@ namespace WebAPI.Migrations b.Property("CreatedById") .HasColumnType("uniqueidentifier"); - b.Property("DataSetId") + b.Property("DataSetId") .HasColumnType("uniqueidentifier"); b.Property("Desc1") @@ -152,7 +152,9 @@ namespace WebAPI.Migrations b.HasOne("WebAPI.Models.DataSet", null) .WithMany("DataRows") - .HasForeignKey("DataSetId"); + .HasForeignKey("DataSetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("WebAPI.Models.User", "ModifiedBy") .WithMany() diff --git a/WebAPI/Models/DataRow.cs b/WebAPI/Models/DataRow.cs index 4578f93..10e28ad 100644 --- a/WebAPI/Models/DataRow.cs +++ b/WebAPI/Models/DataRow.cs @@ -28,6 +28,7 @@ namespace WebAPI.Models [Required] public Guid ModifiedById { get; set; } public User? ModifiedBy { get; set; } + public Guid DataSetId { get; set; } #endregion } } diff --git a/WebAPI/Program.cs b/WebAPI/Program.cs index c30e6b1..756ff03 100644 --- a/WebAPI/Program.cs +++ b/WebAPI/Program.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; +using Newtonsoft.Json.Linq; +using System.IdentityModel.Tokens.Jwt; using System.Text; using WebAPI; @@ -42,6 +44,7 @@ builder.Services.AddAuthentication(options => ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Secret"])) }; + }); builder.Services.AddAuthorization(); @@ -54,7 +57,12 @@ var app = builder.Build(); app.Use(async (context, next) => { - context.Request.Headers.TryGetValue("Authorization", out var auth); + string token = context.Request.Headers["Authorization"].ToString(); + if (token.Length > 0) { + var handler = new JwtSecurityTokenHandler(); + var data = handler.ReadJwtToken(token.Split(' ')[1]); + context.Request.Headers.Add("UserId", new Microsoft.Extensions.Primitives.StringValues(data.Subject)); + } await next(context); }); diff --git a/WebAPI/dataParsers/csv.parser.cs b/WebAPI/dataParsers/csv.parser.cs index f9fe1f4..cad3c46 100644 --- a/WebAPI/dataParsers/csv.parser.cs +++ b/WebAPI/dataParsers/csv.parser.cs @@ -37,6 +37,8 @@ namespace WebAPI.dataParsers dataRow.Code = data[0][i]; dataRow.Desc1 = data[j][0]; dataRow.Value = value; + dataRow.CreatedAt = DateTime.UtcNow; + dataRow.ModifiedAt= DateTime.UtcNow; dataRows.Add(dataRow); } }