From 2f108bef4fb5d1d40e8f96ef4094a16d5df5d46a Mon Sep 17 00:00:00 2001 From: Alexandr Sulimov Date: Thu, 20 Jul 2023 21:38:05 +0300 Subject: [PATCH] update --- MyOffice.Data.Models/Items/Item.cs | 4 +- MyOffice.Data.Models/Items/ItemCategory.cs | 3 +- .../Account/AccountRepository.cs | 8 + .../Account/IAccountyRepository.cs | 1 + .../Item/IItemRepository.cs | 1 + .../Item/ItemRepository.cs | 13 +- .../20230627044606_IsInternal.Designer.cs | 611 ++++++++ .../Migrations/20230627044606_IsInternal.cs | 29 + .../Migrations/AppDbContextModelSnapshot.cs | 25 +- MyOffice.SPA/package.json | 1 + MyOffice.SPA/src/app/api-routes.ts | 2 + .../validators/atleastonenumber.validator.ts | 28 +- .../dashboard2/dashboard2.component.html | 1236 ++++++++--------- .../src/app/model/item.category.model.ts | 1 + MyOffice.SPA/src/app/model/motion.model.ts | 2 +- .../app/pages/accounts/motion.component.html | 39 +- .../app/pages/accounts/motion.component.ts | 97 +- MyOffice.SPA/src/app/pages/pages.module.ts | 8 +- .../item/edit.item.category.component.html | 38 + .../item/edit.item.category.component.scss | 0 .../item/edit.item.category.component.ts | 75 + .../settings/item/edit.item.component.ts | 2 +- .../item/item.category.component.html | 6 +- .../settings/item/item.category.component.ts | 72 +- MyOffice.Services/Account/AccountService.cs | 17 +- .../Account/Domain/MotionAddUpdate.cs | 2 +- MyOffice.Services/Item/ItemService.cs | 316 +++-- MyOffice.Services/MyOffice.Services.csproj | 4 + MyOffice.Web/Controllers/AccountController.cs | 43 +- .../Controllers/DashboardController.cs | 34 + .../Controllers/SettingsItemController.cs | 10 +- .../Models/Item/ItemCategoryViewModel.cs | 21 +- MyOffice.Web/Models/Item/ItemViewModel.cs | 15 +- MyOffice.Web/Models/Motion/MotionRequest.cs | 4 +- MyOffice.Web/Models/Motion/MotionViewModel.cs | 4 +- 35 files changed, 1863 insertions(+), 909 deletions(-) create mode 100644 MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.Designer.cs create mode 100644 MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.cs create mode 100644 MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.html create mode 100644 MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.scss create mode 100644 MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.ts create mode 100644 MyOffice.Web/Controllers/DashboardController.cs diff --git a/MyOffice.Data.Models/Items/Item.cs b/MyOffice.Data.Models/Items/Item.cs index 44ec021..17cb931 100644 --- a/MyOffice.Data.Models/Items/Item.cs +++ b/MyOffice.Data.Models/Items/Item.cs @@ -13,8 +13,8 @@ public class Item /// UnCategorized category is CategoryId = UserId /// public Guid CategoryId { get; set; } - public ItemCategory Category { get; set; } = null!; + public ItemCategory? Category { get; set; } public Guid ItemGlobalId { get; set; } public ItemGlobal ItemGlobal { get; set; } = null!; - public IEnumerable Motions { get; set; } = null!; + public List? Motions { get; set; } } \ No newline at end of file diff --git a/MyOffice.Data.Models/Items/ItemCategory.cs b/MyOffice.Data.Models/Items/ItemCategory.cs index 2d79167..f368199 100644 --- a/MyOffice.Data.Models/Items/ItemCategory.cs +++ b/MyOffice.Data.Models/Items/ItemCategory.cs @@ -8,5 +8,6 @@ public class ItemCategory public Guid UserId { get; set; } public User User { get; set; } = null!; public string Name { get; set; } = null!; - public IEnumerable Items { get; set; } = null!; + public List Items { get; set; } = null!; + public bool IsInternal { get; set; } } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Account/AccountRepository.cs b/MyOffice.Data.Repositories/Account/AccountRepository.cs index 4b2f5ab..aec9ecb 100644 --- a/MyOffice.Data.Repositories/Account/AccountRepository.cs +++ b/MyOffice.Data.Repositories/Account/AccountRepository.cs @@ -90,4 +90,12 @@ public class AccountRepository : AppRepository, IAccountRepository { return RemoveBase(account) > 0; } + + public List FindAccounts(Guid userId, string term) + { + return _context.Accounts + .Where(x => x.AccessRights.Any(a => a.UserId == userId)) + .Where(x => x.Name.Contains(term)) + .ToList(); + } } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Account/IAccountyRepository.cs b/MyOffice.Data.Repositories/Account/IAccountyRepository.cs index f62ce3e..e835ac0 100644 --- a/MyOffice.Data.Repositories/Account/IAccountyRepository.cs +++ b/MyOffice.Data.Repositories/Account/IAccountyRepository.cs @@ -12,4 +12,5 @@ public interface IAccountRepository Account? Get(Guid userId, Guid id); bool Update(Account account); bool Remove(Account account); + List FindAccounts(Guid userId, string term); } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Item/IItemRepository.cs b/MyOffice.Data.Repositories/Item/IItemRepository.cs index 48b519a..00c1ed5 100644 --- a/MyOffice.Data.Repositories/Item/IItemRepository.cs +++ b/MyOffice.Data.Repositories/Item/IItemRepository.cs @@ -10,4 +10,5 @@ public interface IItemRepository Item? GetByGlobal(Guid userId, Guid globalMotionId); bool Add(Item item); bool Update(Item item); + List Find(Guid userId, string term, int limit); } \ No newline at end of file diff --git a/MyOffice.Data.Repositories/Item/ItemRepository.cs b/MyOffice.Data.Repositories/Item/ItemRepository.cs index 9ae6d2a..4c981d1 100644 --- a/MyOffice.Data.Repositories/Item/ItemRepository.cs +++ b/MyOffice.Data.Repositories/Item/ItemRepository.cs @@ -31,7 +31,7 @@ public class ItemRepository : AppRepository, IItemRepository .Include(x => x.Motions) .Include(x => x.Category) .Include(x => x.ItemGlobal) - .FirstOrDefault(x => x.Category.UserId == userId && x.ItemGlobalId == globalMotionId); + .FirstOrDefault(x => x.Category!.UserId == userId && x.ItemGlobalId == globalMotionId); } public bool Update(Item item) @@ -43,4 +43,15 @@ public class ItemRepository : AppRepository, IItemRepository { return base.AddBase(item) > 0; } + + public List Find(Guid userId, string term, int limit) + { + return _context + .Items + .Include(x => x.ItemGlobal) + .Where(x => x.Category!.UserId == userId && x.ItemGlobal.Name.Contains(term)) + .OrderByDescending(x => x.Motions.Count()) + .Take(limit) + .ToList(); + } } \ No newline at end of file diff --git a/MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.Designer.cs b/MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.Designer.cs new file mode 100644 index 0000000..529060a --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.Designer.cs @@ -0,0 +1,611 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using MyOffice.DbContext; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20230627044606_IsInternal")] + partial class IsInternal + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:CollationDefinition:my_ci_collation", "en-u-ks-primary,en-u-ks-primary,icu,False") + .HasAnnotation("ProductVersion", "7.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.ToTable("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("IsAllowManage") + .HasColumnType("boolean"); + + b.Property("IsAllowRead") + .HasColumnType("boolean"); + + b.Property("IsAllowWrite") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("UserId"); + + b.ToTable("AccountAccesses"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("CategoryId"); + + b.ToTable("AccountAccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AccountCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("uuid"); + + b.Property("AmountMinus") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("AmountPlus") + .HasPrecision(18, 6) + .HasColumnType("numeric(18,6)"); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ItemId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("ItemId"); + + b.HasIndex("UserId"); + + b.ToTable("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyGlobalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShortName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyGlobalId"); + + b.HasIndex("UserId"); + + b.ToTable("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DefaultQuantity") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Symbol") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("CurrencyGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyId") + .HasColumnType("uuid"); + + b.Property("DateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Quantity") + .HasColumnType("integer"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("CurrencyRates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("ItemGlobalId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("ItemGlobalId"); + + b.ToTable("Items"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IsInternal") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ItemCategories"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ItemGlobals"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CurrencyId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("IsEmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("text"); + + b.Property("Phone") + .HasColumnType("text"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.HasKey("Id"); + + b.HasIndex("CurrencyId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("ExternalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Provider") + .IsRequired() + .HasColumnType("text") + .UseCollation("my_ci_collation"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b => + { + b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal") + .WithMany("Accounts") + .HasForeignKey("CurrencyGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("AccessRights") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("AccountAccess") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("Categories") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Accounts.AccountCategory", "Category") + .WithMany("Accounts") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("AccountCategories") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b => + { + b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account") + .WithMany("Motions") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Items.Item", "Item") + .WithMany("Motions") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", null) + .WithMany("AccountMotions") + .HasForeignKey("UserId"); + + b.Navigation("Account"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal") + .WithMany("Currencies") + .HasForeignKey("CurrencyGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("Currencies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CurrencyGlobal"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b => + { + b.HasOne("MyOffice.Data.Models.Currencies.Currency", "Currency") + .WithMany("Rates") + .HasForeignKey("CurrencyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Currency"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b => + { + b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category") + .WithMany("Items") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal") + .WithMany("Items") + .HasForeignKey("ItemGlobalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("ItemGlobal"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("ItemCategories") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "Currency") + .WithMany() + .HasForeignKey("CurrencyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Currency"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b => + { + b.HasOne("MyOffice.Data.Models.Users.User", "User") + .WithMany("UserClaims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b => + { + b.Navigation("AccessRights"); + + b.Navigation("Categories"); + + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b => + { + b.Navigation("Accounts"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b => + { + b.Navigation("Rates"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b => + { + b.Navigation("Accounts"); + + b.Navigation("Currencies"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b => + { + b.Navigation("Motions"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("MyOffice.Data.Models.Users.User", b => + { + b.Navigation("AccountAccess"); + + b.Navigation("AccountCategories"); + + b.Navigation("AccountMotions"); + + b.Navigation("Currencies"); + + b.Navigation("ItemCategories"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.cs b/MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.cs new file mode 100644 index 0000000..65fe3c4 --- /dev/null +++ b/MyOffice.Migration.Postgres/Migrations/20230627044606_IsInternal.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace MyOffice.Migrations.Postgres.Migrations +{ + /// + public partial class IsInternal : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsInternal", + table: "ItemCategories", + type: "boolean", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsInternal", + table: "ItemCategories"); + } + } +} diff --git a/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs b/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs index 9f26b03..b829960 100644 --- a/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs +++ b/MyOffice.Migration.Postgres/Migrations/AppDbContextModelSnapshot.cs @@ -240,7 +240,7 @@ namespace MyOffice.Migrations.Postgres.Migrations b.ToTable("CurrencyRates"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.Item", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -263,12 +263,15 @@ namespace MyOffice.Migrations.Postgres.Migrations b.ToTable("Items"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.ItemCategory", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("IsInternal") + .HasColumnType("boolean"); + b.Property("Name") .IsRequired() .HasColumnType("text"); @@ -283,7 +286,7 @@ namespace MyOffice.Migrations.Postgres.Migrations b.ToTable("ItemCategories"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.ItemGlobal", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -447,7 +450,7 @@ namespace MyOffice.Migrations.Postgres.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("MyOffice.Data.Models.Motions.Item", "Item") + b.HasOne("MyOffice.Data.Models.Items.Item", "Item") .WithMany("Motions") .HasForeignKey("ItemId") .OnDelete(DeleteBehavior.Cascade) @@ -492,15 +495,15 @@ namespace MyOffice.Migrations.Postgres.Migrations b.Navigation("Currency"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.Item", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b => { - b.HasOne("MyOffice.Data.Models.Motions.ItemCategory", "Category") + b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category") .WithMany("Items") .HasForeignKey("CategoryId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("MyOffice.Data.Models.Motions.ItemGlobal", "ItemGlobal") + b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal") .WithMany("Items") .HasForeignKey("ItemGlobalId") .OnDelete(DeleteBehavior.Cascade) @@ -511,7 +514,7 @@ namespace MyOffice.Migrations.Postgres.Migrations b.Navigation("ItemGlobal"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.ItemCategory", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b => { b.HasOne("MyOffice.Data.Models.Users.User", "User") .WithMany("ItemCategories") @@ -570,17 +573,17 @@ namespace MyOffice.Migrations.Postgres.Migrations b.Navigation("Currencies"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.Item", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b => { b.Navigation("Motions"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.ItemCategory", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b => { b.Navigation("Items"); }); - modelBuilder.Entity("MyOffice.Data.Models.Motions.ItemGlobal", b => + modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b => { b.Navigation("Items"); }); diff --git a/MyOffice.SPA/package.json b/MyOffice.SPA/package.json index a6496ce..a4dd4e3 100644 --- a/MyOffice.SPA/package.json +++ b/MyOffice.SPA/package.json @@ -44,6 +44,7 @@ "@swimlane/ngx-charts": "^20.1.2", "@swimlane/ngx-datatable": "^20.1.0", "@types/d3-shape": "^3.1.1", + "angular-animations": "^0.11.0", "angular-auth-oidc-client": "^15.0.3", "angular-feather": "^6.5.0", "angular-gauge": "^4.0.0", diff --git a/MyOffice.SPA/src/app/api-routes.ts b/MyOffice.SPA/src/app/api-routes.ts index 733acc1..59a65bd 100644 --- a/MyOffice.SPA/src/app/api-routes.ts +++ b/MyOffice.SPA/src/app/api-routes.ts @@ -28,4 +28,6 @@ export class ApiRoutes { static Motions = '/api/accounts/:id/motions'; static Motion = '/api/accounts/:id/motions/:motionId'; + + static Items = '/api/items'; } diff --git a/MyOffice.SPA/src/app/core/validators/atleastonenumber.validator.ts b/MyOffice.SPA/src/app/core/validators/atleastonenumber.validator.ts index c6a66d6..49cdcb2 100644 --- a/MyOffice.SPA/src/app/core/validators/atleastonenumber.validator.ts +++ b/MyOffice.SPA/src/app/core/validators/atleastonenumber.validator.ts @@ -5,20 +5,20 @@ import { Validators, } from '@angular/forms'; -export const atLeastOneNumber = (validator: ValidatorFn, controls: string[] = []) => ( - group: FormGroup, -): ValidationErrors | null => { - if (!controls) { - controls = Object.keys(group.controls); - } +export const atLeastOneNumber = (validator: ValidatorFn, controls: string[] = []) => + (group: FormGroup,): ValidationErrors | null => { - const hasAtLeastOne = group && group.controls && controls - .some(k => { - var v = group.controls[k].value; - return v && !isNaN(v) && v !== 0 && !validator(group.controls[k]); - }); + if (!controls) { + controls = Object.keys(group.controls); + } - return hasAtLeastOne ? null : { - atLeastOne: true, + const hasAtLeastOne = group && group.controls && controls + .some(k => { + var v = group.controls[k].value; + return !!(v && !isNaN(v) && parseFloat(v) !== 0 && !validator(group.controls[k])); + }); + + return hasAtLeastOne ? null : { + atLeastOne: true, + }; }; -}; diff --git a/MyOffice.SPA/src/app/dashboard/dashboard2/dashboard2.component.html b/MyOffice.SPA/src/app/dashboard/dashboard2/dashboard2.component.html index e4e1783..aa5cb94 100644 --- a/MyOffice.SPA/src/app/dashboard/dashboard2/dashboard2.component.html +++ b/MyOffice.SPA/src/app/dashboard/dashboard2/dashboard2.component.html @@ -1,642 +1,622 @@
-
-
- - -
-
-
-
-
-
-
-
Todays Income
-

Income For Today

-
-

$170

-
-
-
-
-
-
-
-
-

Change

-

75%

-
-
+
+
+ +
-
-
-
-
-
-
-
Total Revenue
-

Total Income

+ +
+ +
+
+
+
+
+
Income
+

Income last 7 days

+
+

$170

-

$120

-
-
-
-
-
-
-
-
-

Change

-

25%

-
-
-
-
-
-
-
-
-
-
New Orders
-

Fresh New Order

-
-

15

-
-
-
-
-
-
-
-
-

Change

-

50%

-
-
-
-
-
-
-
-
-
-
New Users
-

Joined New User

-
-

12

-
-
-
-
-
-
-
-
-

Change

-

25%

-
-
-
-
-
-
- -
-
-
-

Products Performance

- - - - - - -
-
-
- - -
-
-
-
-
-
-
-

Country Wise Clients

- - - - - - -
-
-
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - -
India23+32%
USA32+12%
Shrilanka12-12%
Australia32+3%
-
-
-
-
-
-
-
-
-
-

Notice Board

- - - - - - -
-
- -
-
-
- ... -
-
-
Airi Satou
-

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

- 7 hours ago -
-
-
-
- ... -
-
-
Sarah Smith
-

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

-

1 hour ago

-
-
-
-
- ... -
-
-
Cara Stevens
-

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

-
Yesterday
-
-
-
-
- ... -
-
-
Ashton Cox
-

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

-
Yesterday
-
-
-
-
- ... -
-
-
Mark Hay
-

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

-

1 hour ago

-
-
-
-
- ... -
-
-
Jay Pandya
-

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

-

3 hour ago

-
-
-
-
-
-
-
-
-
-
-

Project Status

- - - - - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Project NameProgressDuration
Project A - 30% - - - 2 Months
Project B - 55% - - - 3 Months
Project C - 67% - - - 1 Months
Project D - 70% - - - 2 Months
Project E - 24% - - - 3 Months
Project F - 77% - - - 4 Months
Project G - 41% - - - 2 Months
Project H - 41% - - - 2 Months
-
-
-
-
-
-
-
-
-

Earning Source

- - - - - - -
-
-
-

$90,808

-
-
-
    -
  • -
    - envato.com - 17% -
    -
    -
    +
    +
    -
  • -
  • -
    - google.com - 27% -
    -
    -
    -
    -
    -
  • -
  • -
    - yahoo.com - 25% -
    -
    -
    -
    -
    -
  • -
  • -
    - store - 18% -
    -
    -
    -
    -
    -
  • -
  • -
    - Others - 13% -
    -
    -
    -
    -
    -
  • -
+
+
+

Change previous 7 days

+

75%

+
+
-
-
-
-
-
-
-
-

Recent Orders

- - - - - - + +
+
+
+
+
+
Outcome
+

Outcome last 7 days

+
+

$120

+
+
+
+
+
+
+
+
+

Change previous 7 days

+

25%

+
+
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Order IDCustomer NameItemOrder DateQuantityPaymentStatusInvoiceDetails
ID7865 - Jens - Brincker - iPhone X22/05/20212Credit Card -
Paid
-
- - - -
ID9357 - Mark Harry - Pixel 212/06/20211COD -
Unpaid
-
- - - -
ID3987 - Anthony - Davie - OnePlus02/02/20215Debit Card -
Pending
-
- - - -
ID2483 - David Perry - Moto Z210/01/20212Credit Card -
Paid
-
- - - -
ID2986 - John Doe - Samsung F6220/05/20213Net Banking -
Unpaid
-
- - - -
ID1267 - Sarah Smith - iPhone 1210/07/20211COD -
Paid
-
- - - -
ID3398 - Cara Stevens - Moto Gs511/04/20212UPI Payment -
Pending
-
- - - -
ID9965 - Ashton Cox - Pixel 214/05/20214Credit Card -
Paid
-
- - - -
+
+ +
+
+
+
+
+
New Orders
+

Fresh New Order

+
+

15

+
+
+
+
+
+
+
+
+

Change

+

50%

+
+
+
+
+ +
+
+
+
+
+
New Users
+

Joined New User

+
+

12

+
+
+
+
+
+
+
+
+

Change

+

25%

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

Current rest

+ + + + + + +
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
India23+32%
USA32+12%
Shrilanka12-12%
Australia32+3%
+
+
+
+
+
+
+
+
+
+

Notice Board

+ + + + + + +
+
+ +
+
+
+ ... +
+
+
Airi Satou
+

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

+ 7 hours ago +
+
+
+
+ ... +
+
+
Sarah Smith
+

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

+

1 hour ago

+
+
+
+
+ ... +
+
+
Cara Stevens
+

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

+
Yesterday
+
+
+
+
+ ... +
+
+
Ashton Cox
+

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

+
Yesterday
+
+
+
+
+ ... +
+
+
Mark Hay
+

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

+

1 hour ago

+
+
+
+
+ ... +
+
+
Jay Pandya
+

Lorem ipsum dolor sit amet, id quo eruditi eloquentiam.

+

3 hour ago

+
+
+
+
+
+
+
+
+
+
+

Project Status

+ + + + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Project NameProgressDuration
Project A + 30% + + + 2 Months
Project B + 55% + + + 3 Months
Project C + 67% + + + 1 Months
Project D + 70% + + + 2 Months
Project E + 24% + + + 3 Months
Project F + 77% + + + 4 Months
Project G + 41% + + + 2 Months
Project H + 41% + + + 2 Months
+
+
+
+
+
+
+
+
+

Earning Source

+ + + + + + +
+
+
+

$90,808

+
+
+
    +
  • +
    + envato.com + 17% +
    +
    +
    +
    +
    +
  • +
  • +
    + google.com + 27% +
    +
    +
    +
    +
    +
  • +
  • +
    + yahoo.com + 25% +
    +
    +
    +
    +
    +
  • +
  • +
    + store + 18% +
    +
    +
    +
    +
    +
  • +
  • +
    + Others + 13% +
    +
    +
    +
    +
    +
  • +
+
+
+
+
+
+
+
+
+
+

Recent Orders

+ + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Order IDCustomer NameItemOrder DateQuantityPaymentStatusInvoiceDetails
ID7865 + Jens + Brincker + iPhone X22/05/20212Credit Card +
Paid
+
+ + + +
ID9357 + Mark Harry + Pixel 212/06/20211COD +
Unpaid
+
+ + + +
ID3987 + Anthony + Davie + OnePlus02/02/20215Debit Card +
Pending
+
+ + + +
ID2483 + David Perry + Moto Z210/01/20212Credit Card +
Paid
+
+ + + +
ID2986 + John Doe + Samsung F6220/05/20213Net Banking +
Unpaid
+
+ + + +
ID1267 + Sarah Smith + iPhone 1210/07/20211COD +
Paid
+
+ + + +
ID3398 + Cara Stevens + Moto Gs511/04/20212UPI Payment +
Pending
+
+ + + +
ID9965 + Ashton Cox + Pixel 214/05/20214Credit Card +
Paid
+
+ + + +
+
+
-
-
diff --git a/MyOffice.SPA/src/app/model/item.category.model.ts b/MyOffice.SPA/src/app/model/item.category.model.ts index ad475e0..304f7b3 100644 --- a/MyOffice.SPA/src/app/model/item.category.model.ts +++ b/MyOffice.SPA/src/app/model/item.category.model.ts @@ -2,4 +2,5 @@ export interface ItemCategoryModel { id?: string, name?: string, allowDelete: boolean, + isInternal: boolean, } diff --git a/MyOffice.SPA/src/app/model/motion.model.ts b/MyOffice.SPA/src/app/model/motion.model.ts index 5bcc33d..2190b2a 100644 --- a/MyOffice.SPA/src/app/model/motion.model.ts +++ b/MyOffice.SPA/src/app/model/motion.model.ts @@ -1,7 +1,7 @@ export interface MotionModel { id?: string; date?: Date; - motion?: string; + item?: string; description?: string; plus?: number; minus?: number; diff --git a/MyOffice.SPA/src/app/pages/accounts/motion.component.html b/MyOffice.SPA/src/app/pages/accounts/motion.component.html index 6d62e2b..09a8bd0 100644 --- a/MyOffice.SPA/src/app/pages/accounts/motion.component.html +++ b/MyOffice.SPA/src/app/pages/accounts/motion.component.html @@ -1,4 +1,4 @@ -
+
@@ -7,7 +7,7 @@ - + YYYY/MM/DD @@ -23,11 +23,19 @@
- Motion - - + + Motion + !! + + + Please enter motion + + + {{item.name}} + + @@ -36,17 +44,18 @@
+ + Please enter motion + + + Please enter motion +
- @@ -59,6 +68,16 @@ +
+
+
+
+
+
+
+
+
+

diff --git a/MyOffice.SPA/src/app/pages/accounts/motion.component.ts b/MyOffice.SPA/src/app/pages/accounts/motion.component.ts index cf9522c..ebc6cb7 100644 --- a/MyOffice.SPA/src/app/pages/accounts/motion.component.ts +++ b/MyOffice.SPA/src/app/pages/accounts/motion.component.ts @@ -13,21 +13,31 @@ import { ElementRef } from '@angular/core'; // libs import * as moment from 'moment'; import Swal from 'sweetalert2'; +import { Observable } from 'rxjs'; +import { pulseAnimation } from 'angular-animations'; // app import { ApiRoutes } from '../../api-routes'; import { AccountModel } from '../../model/account.model'; import { MotionModel } from '../../model/motion.model'; +import { ItemModel } from '../../model/item.model'; import { atLeastOneNumber } from '../../core/validators/atleastonenumber.validator'; @Component({ selector: 'account-motion', templateUrl: './motion.component.html', styleUrls: ['./motion.component.scss'], + animations: [ + pulseAnimation({ direction: '<=>', duration: 200 }), + ], }) export class MotionComponent { public form!: FormGroup; public errorMessage?: string; + public filteredItems: ItemModel[] = []; + public option?: string; + public selectedItem?: ItemModel; + public inProgress: boolean = false; @Input('motion') motion!: MotionModel; @Input('account') account!: AccountModel; @@ -36,6 +46,7 @@ export class MotionComponent { @Output() onDelete: EventEmitter = new EventEmitter(); @ViewChild('motionInput') motionInput?: ElementRef; + @ViewChild('dateInput') dateInput?: ElementRef; constructor( private fb: FormBuilder, @@ -52,8 +63,8 @@ export class MotionComponent { this.motion.date, [Validators.required], ], - motion: [ - this.motion.motion, + item: [ + this.motion.item, [Validators.required], ], description: [ @@ -68,46 +79,112 @@ export class MotionComponent { }, { validator: atLeastOneNumber(Validators.required, ['plus', 'minus']) }); + + this.form.controls['item'].valueChanges.subscribe(value => { + if (!value) { + return; + } + + this.selectedItem = undefined; + + this.httpClient + .get(ApiRoutes.Items + '?term=' + encodeURIComponent(value)) + .subscribe(x => { + this.filteredItems = x; + }); + }); + } + + displayFn(item: any): string { + var value = item && item.name ? item.name : item; + return value; + } + + selectedFn(item: ItemModel) { + this.selectedItem = item; } add() { this.form.markAllAsTouched(); + if (!this.form.valid) { + if (this.form.hasError('atLeastOne')) { + this.form.get('plus')!.setErrors(this.form.errors); + this.form.get('minus')!.setErrors(this.form.errors); + } + return; + } + + this.setInProgress(); + + var data = this.form.value; + data.motion = data.item.name + ? data.item.name + : data.item; + data.itemId = this.selectedItem?.id; + this.httpClient - .post(ApiRoutes.Motions.replace(':id', this.account.id!), this.form.value) + .post(ApiRoutes.Motions.replace(':id', this.account.id!), data) .subscribe(response => { this.onAdd?.emit(response); this.form.patchValue({ - motion: '', + item: '', plus: 0, minus: 0, }); - this.form.markAsUntouched(); + this.filteredItems = []; this.motionInput?.nativeElement.focus(); + this.form.markAsUntouched(); + this.setInProgress(false); }, error => { this.errorMessage = error.detail; + this.setInProgress(false); }); } + private setInProgress(inProgress: boolean = true) { + this.inProgress = inProgress; + } + update() { + this.form.markAllAsTouched(); + + if (!this.form.valid) { + if (this.form.hasError('atLeastOne')) { + this.form.get('plus')!.setErrors(this.form.errors); + this.form.get('minus')!.setErrors(this.form.errors); + } + return; + } + + this.setInProgress(); + var url = ApiRoutes.Motion .replace(':id', this.account.id!) .replace(':motionId', this.motion.id!); - + + var data = this.form.value; + data.motion = data.item.name + ? data.item.name + : data.motion; + data.itemId = this.selectedItem?.id; + this.httpClient - .put(url, this.form.value) + .put(url, data) .subscribe(response => { this.form.markAsUntouched(); + this.setInProgress(false); }, error => { this.errorMessage = error.detail; + this.setInProgress(false); }); } delete() { Swal.fire({ - title: 'Delete motion ' + this.motion.motion, + title: 'Delete motion ' + this.motion.item, showCancelButton: true, confirmButtonText: 'Delete', showLoaderOnConfirm: true, @@ -117,12 +194,16 @@ export class MotionComponent { .replace(':id', this.account.id!) .replace(':motionId', this.motion.id!); + this.setInProgress(); + this.httpClient.delete(url) .subscribe(data => { resolve(data); + this.setInProgress(false); }, error => { Swal.showValidationMessage(error.detail); reject(); + this.setInProgress(false); }); }).catch(x => { diff --git a/MyOffice.SPA/src/app/pages/pages.module.ts b/MyOffice.SPA/src/app/pages/pages.module.ts index 04f13ac..b159d11 100644 --- a/MyOffice.SPA/src/app/pages/pages.module.ts +++ b/MyOffice.SPA/src/app/pages/pages.module.ts @@ -19,6 +19,8 @@ import { MatCardModule } from '@angular/material/card'; import { NgxMaskModule } from 'ngx-mask'; import { NgxCurrencyModule } from "ngx-currency"; import { MatExpansionModule } from '@angular/material/expansion'; +import { MatAutocompleteModule } from '@angular/material/autocomplete'; +import { MatCheckboxModule } from '@angular/material/checkbox'; // app import { PagesRoutingModule } from './pages-routing.module'; @@ -39,6 +41,7 @@ import { SettingsItemEditComponent } from './settings/item/edit.item.component'; import { AccountListComponent } from './accounts/account.list.component'; import { AccountComponent } from './accounts/account.component'; import { MotionComponent } from './accounts/motion.component'; +import { SettingsItemCategoryEditComponent } from './settings/item/edit.item.category.component'; @NgModule({ declarations: [ @@ -56,6 +59,7 @@ import { MotionComponent } from './accounts/motion.component'; SettingsItemCategoryComponent, SettingsItemComponent, SettingsItemEditComponent, + SettingsItemCategoryEditComponent, AccountListComponent, AccountComponent, @@ -78,8 +82,10 @@ import { MotionComponent } from './accounts/motion.component'; MatGridListModule, MatCardModule, MatExpansionModule, + MatAutocompleteModule, NgxMaskModule, - NgxCurrencyModule + NgxCurrencyModule, + MatCheckboxModule, ], providers: [ { provide: MAT_DATE_LOCALE, useValue: 'en-GB' }, diff --git a/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.html b/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.html new file mode 100644 index 0000000..6c99e60 --- /dev/null +++ b/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.html @@ -0,0 +1,38 @@ +
+

+ Edit item category +

+
+ +
+
+
+ + Name + + +
+
+
+
+ Is internal motion +
+
+
+ +
+
+ {{errorMessage}} +
+
+
+
+ + +
+
+
+ + +
+
diff --git a/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.scss b/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.ts b/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.ts new file mode 100644 index 0000000..fe60a65 --- /dev/null +++ b/MyOffice.SPA/src/app/pages/settings/item/edit.item.category.component.ts @@ -0,0 +1,75 @@ +// angular +import { Component } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Inject } from '@angular/core'; +import { UntypedFormBuilder } from '@angular/forms'; +import { UntypedFormGroup } from '@angular/forms'; +import { Validators } from '@angular/forms'; + +// libs +import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatDialogRef } from '@angular/material/dialog'; + +// app +import { ApiRoutes } from '../../../api-routes'; +import { ItemCategoryModel } from '../../../model/item.category.model'; + +@Component({ + templateUrl: './edit.item.category.component.html', + styleUrls: ['./edit.item.category.component.scss'], +}) +export class SettingsItemCategoryEditComponent { + public editForm!: UntypedFormGroup; + public errorMessage?: string; + + constructor( + private fb: UntypedFormBuilder, + private httpClient: HttpClient, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public category: ItemCategoryModel + ) { + } + + ngOnInit(): void { + this.editForm = this.fb.group({ + id: [ + this.category.id, + ], + name: [ + this.category.name, + [Validators.required], + ], + isInternal: [ + this.category.isInternal, + ], + }); + console.log(this.editForm.value); + } + + closeDialog(): void { + this.dialogRef.close(); + } + + onSubmitClick() { + if (this.editForm.valid) { + this.errorMessage = undefined; + if (!this.category.id) { + this.httpClient + .post(ApiRoutes.SettingsItemCategories, this.editForm.value) + .subscribe(response => { + this.dialogRef.close({ category: response, refresh: true }); + }, error => { + this.errorMessage = error.detail; + }); + } else { + this.httpClient + .put(ApiRoutes.SettingsItemCategory.replace(':id', this.category.id!), this.editForm.value) + .subscribe(response => { + this.dialogRef.close({ category: response, refresh: true }); + }, error => { + this.errorMessage = error.detail; + }); + } + } + } +} diff --git a/MyOffice.SPA/src/app/pages/settings/item/edit.item.component.ts b/MyOffice.SPA/src/app/pages/settings/item/edit.item.component.ts index 2542942..760bb62 100644 --- a/MyOffice.SPA/src/app/pages/settings/item/edit.item.component.ts +++ b/MyOffice.SPA/src/app/pages/settings/item/edit.item.component.ts @@ -8,10 +8,10 @@ import { Validators } from '@angular/forms'; // libs import { MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatDialogRef } from '@angular/material/dialog'; // app import { ApiRoutes } from '../../../api-routes'; -import { MatDialogRef } from '@angular/material/dialog'; import { ItemCategoryModel } from '../../../model/item.category.model'; import { ItemModel } from '../../../model/item.model'; import { ItemService } from '../../../services/item.service'; diff --git a/MyOffice.SPA/src/app/pages/settings/item/item.category.component.html b/MyOffice.SPA/src/app/pages/settings/item/item.category.component.html index 9709325..e303398 100644 --- a/MyOffice.SPA/src/app/pages/settings/item/item.category.component.html +++ b/MyOffice.SPA/src/app/pages/settings/item/item.category.component.html @@ -2,7 +2,7 @@
- +
@@ -11,7 +11,6 @@ - Motion categories @@ -27,6 +26,9 @@ {{item.name}} + + done +