From 0bf572d84439f6c55aa21513e8e33780aeb306a8 Mon Sep 17 00:00:00 2001 From: Mateusz Skoczek Date: Sun, 10 Nov 2024 14:33:41 +0100 Subject: [PATCH] following added --- .../Account/AccountFollowConfiguration.cs | 2 +- .../WatchIt.Database.Model/Account/Account.cs | 2 +- .../WatchIt.Database/DatabaseContext.cs | 1 + .../20241109182449_RelationRename.Designer.cs | 1459 +++++++++++++++++ .../20241109182449_RelationRename.cs | 136 ++ .../DatabaseContextModelSnapshot.cs | 12 +- .../AccountsController.cs | 33 + .../AccountsControllerService.cs | 75 + .../IAccountsControllerService.cs | 4 + .../Accounts/AccountsClientService.cs | 125 +- .../Accounts/IAccountsClientService.cs | 12 +- .../Model/Accounts.cs | 4 + WatchIt.Website/WatchIt.Website/App.razor | 2 +- .../UserListItemComponent.razor} | 2 +- .../UserListItemComponent.razor.cs} | 5 +- .../UsersSearchResultPanelComponent.razor | 3 +- .../Panels/FollowListPanelComponent.razor | 29 + .../Panels/FollowListPanelComponent.razor.cs | 41 + .../Panels/UserPageHeaderPanelComponent.razor | 40 +- .../UserPageHeaderPanelComponent.razor.cs | 48 +- .../WatchIt.Website/Pages/UserPage.razor | 40 +- .../WatchIt.Website/Pages/UserPage.razor.cs | 19 +- .../WatchIt.Website/appsettings.json | 6 +- .../WatchIt.Website/wwwroot/css/general.css | 5 + 24 files changed, 2015 insertions(+), 90 deletions(-) create mode 100644 WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.Designer.cs create mode 100644 WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.cs rename WatchIt.Website/WatchIt.Website/Components/{Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor => Common/Subcomponents/UserListItemComponent.razor} (80%) rename WatchIt.Website/WatchIt.Website/Components/{Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor.cs => Common/Subcomponents/UserListItemComponent.razor.cs} (51%) create mode 100644 WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor create mode 100644 WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor.cs diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Account/AccountFollowConfiguration.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Account/AccountFollowConfiguration.cs index 18f237e..89d1bf2 100644 --- a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Account/AccountFollowConfiguration.cs +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model.Configuration/Account/AccountFollowConfiguration.cs @@ -22,7 +22,7 @@ public class AccountFollowConfiguration : IEntityTypeConfiguration x.AccountFollowed) - .WithMany(x => x.AccountFollowedBy) + .WithMany(x => x.AccountFollowers) .HasForeignKey(x => x.AccountFollowedId) .IsRequired(); builder.Property(x => x.AccountFollowedId) diff --git a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs index 181dd59..227a740 100644 --- a/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs +++ b/WatchIt.Database/WatchIt.Database.Model/WatchIt.Database.Model/Account/Account.cs @@ -41,7 +41,7 @@ public class Account public virtual IEnumerable AccountRefreshTokens { get; set; } = new List(); public virtual IEnumerable AccountFollows { get; set; } = new List(); - public virtual IEnumerable AccountFollowedBy { get; set; } = new List(); + public virtual IEnumerable AccountFollowers { get; set; } = new List(); #endregion } \ No newline at end of file diff --git a/WatchIt.Database/WatchIt.Database/DatabaseContext.cs b/WatchIt.Database/WatchIt.Database/DatabaseContext.cs index d04598f..790dc64 100644 --- a/WatchIt.Database/WatchIt.Database/DatabaseContext.cs +++ b/WatchIt.Database/WatchIt.Database/DatabaseContext.cs @@ -40,6 +40,7 @@ public class DatabaseContext : DbContext // Account public virtual DbSet Accounts { get; set; } + public virtual DbSet AccountFollows { get; set; } public virtual DbSet AccountProfilePictures { get; set; } public virtual DbSet AccountRefreshTokens { get; set; } diff --git a/WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.Designer.cs b/WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.Designer.cs new file mode 100644 index 0000000..eb8af24 --- /dev/null +++ b/WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.Designer.cs @@ -0,0 +1,1459 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using WatchIt.Database; + +#nullable disable + +namespace WatchIt.Database.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20241109182449_RelationRename")] + partial class RelationRename + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.5") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true) + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BackgroundPictureId") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(320) + .HasColumnType("character varying(320)"); + + b.Property("GenderId") + .HasColumnType("smallint"); + + b.Property("IsAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("LastActive") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("LeftSalt") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("bytea"); + + b.Property("ProfilePictureId") + .HasColumnType("uuid"); + + b.Property("RightSalt") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Id"); + + b.HasIndex("BackgroundPictureId"); + + b.HasIndex("GenderId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("ProfilePictureId") + .IsUnique(); + + b.ToTable("Accounts"); + + b.HasData( + new + { + Id = 1L, + CreationDate = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + Email = "root@watch.it", + IsAdmin = true, + LastActive = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + LeftSalt = "QkJky0:m43g!mRL_-0S'", + Password = new byte[] { 104, 21, 33, 198, 192, 7, 229, 80, 195, 46, 190, 26, 125, 243, 113, 195, 194, 9, 145, 142, 56, 34, 125, 141, 133, 113, 14, 172, 29, 90, 194, 60, 98, 40, 121, 132, 218, 157, 80, 128, 70, 136, 201, 208, 36, 37, 124, 215, 144, 242, 212, 68, 209, 27, 248, 191, 212, 84, 250, 35, 230, 51, 218, 15 }, + RightSalt = "~-jO$aMa{Q9lAW~>)Z+Z", + Username = "root" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountFollow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountFollowedId") + .HasColumnType("bigint"); + + b.Property("AccountFollowerId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("AccountFollowedId"); + + b.HasIndex("AccountFollowerId"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("AccountFollows"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountProfilePicture", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("AccountProfilePictures"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountRefreshToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("IsExtendable") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("AccountRefreshTokens"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Country", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("IsHistorical") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("Countries"); + + b.HasData( + new + { + Id = (short)1, + IsHistorical = false, + Name = "Afghanistan" + }, + new + { + Id = (short)2, + IsHistorical = false, + Name = "Albania" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Gender", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("Genders"); + + b.HasData( + new + { + Id = (short)1, + Name = "Male" + }, + new + { + Id = (short)2, + Name = "Female" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("Genres"); + + b.HasData( + new + { + Id = (short)1, + Name = "Comedy" + }, + new + { + Id = (short)2, + Name = "Thriller" + }, + new + { + Id = (short)3, + Name = "Horror" + }, + new + { + Id = (short)4, + Name = "Action" + }, + new + { + Id = (short)5, + Name = "Drama" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.Media", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("Length") + .HasColumnType("smallint"); + + b.Property("MediaPosterImageId") + .HasColumnType("uuid"); + + b.Property("OriginalTitle") + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("ReleaseDate") + .HasColumnType("date"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaPosterImageId") + .IsUnique(); + + b.ToTable("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaGenre", b => + { + b.Property("GenreId") + .HasColumnType("smallint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("GenreId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("MediaGenres"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaMovie", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("Budget") + .HasColumnType("money"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaMovies"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.ToTable("MediaPhotoImages"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("FirstGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.Property("IsUniversalBackground") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SecondGradientColor") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaPhotoImageBackgrounds"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaPosterImages"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaProductionCountry", b => + { + b.Property("CountryId") + .HasColumnType("smallint"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.HasKey("CountryId", "MediaId"); + + b.HasIndex("MediaId"); + + b.ToTable("MediaProductionCountries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("HasEnded") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("MediaSeries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IsSpecial") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("MediaSeriesSeasonId") + .HasColumnType("uuid"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesSeasonId"); + + b.ToTable("MediaSeriesEpisodes"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesSeason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MediaSeriesId") + .HasColumnType("bigint"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesId"); + + b.ToTable("MediaSeriesSeasons"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.Person", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BirthDate") + .HasColumnType("date"); + + b.Property("DeathDate") + .HasColumnType("date"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("character varying(1000)"); + + b.Property("FullName") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("GenderId") + .HasColumnType("smallint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PersonPhotoId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GenderId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonPhotoId") + .IsUnique(); + + b.ToTable("Persons"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("PersonActorRoleTypeId") + .HasColumnType("smallint"); + + b.Property("PersonId") + .HasColumnType("bigint"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.HasIndex("PersonActorRoleTypeId"); + + b.HasIndex("PersonId"); + + b.ToTable("PersonActorRoles"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRoleType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("PersonActorRoleTypes"); + + b.HasData( + new + { + Id = (short)1, + Name = "Actor" + }, + new + { + Id = (short)2, + Name = "Supporting actor" + }, + new + { + Id = (short)3, + Name = "Voice actor" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("PersonCreatorRoleTypeId") + .HasColumnType("smallint"); + + b.Property("PersonId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.HasIndex("PersonCreatorRoleTypeId"); + + b.HasIndex("PersonId"); + + b.ToTable("PersonCreatorRoles"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRoleType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("smallint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("PersonCreatorRoleTypes"); + + b.HasData( + new + { + Id = (short)1, + Name = "Director" + }, + new + { + Id = (short)2, + Name = "Producer" + }, + new + { + Id = (short)3, + Name = "Screenwriter" + }); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonPhotoImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Image") + .IsRequired() + .HasMaxLength(-1) + .HasColumnType("bytea"); + + b.Property("MimeType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UploadDate") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.ToTable("PersonPhotoImages"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMedia", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.ToTable("RatingsMedia"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("MediaSeriesEpisodeId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesEpisodeId"); + + b.ToTable("RatingsMediaSeriesEpisode"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesSeason", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("MediaSeriesSeasonId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaSeriesSeasonId"); + + b.ToTable("RatingsMediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonActorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("PersonActorRoleId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonActorRoleId"); + + b.ToTable("RatingsPersonActorRole", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonCreatorRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccountId") + .HasColumnType("bigint"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("PersonCreatorRoleId") + .HasColumnType("uuid"); + + b.Property("Rating") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("AccountId"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonCreatorRoleId"); + + b.ToTable("RatingsPersonCreatorRole", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountMedia", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("date") + .HasDefaultValueSql("now()"); + + b.Property("MediaId") + .HasColumnType("bigint"); + + b.Property("ViewCount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("MediaId"); + + b.ToTable("ViewCountsMedia", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountPerson", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .ValueGeneratedOnAdd() + .HasColumnType("date") + .HasDefaultValueSql("now()"); + + b.Property("PersonId") + .HasColumnType("bigint"); + + b.Property("ViewCount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L); + + b.HasKey("Id"); + + b.HasIndex("Id") + .IsUnique(); + + b.HasIndex("PersonId"); + + b.ToTable("ViewCountsPerson", (string)null); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImage", "BackgroundPicture") + .WithMany() + .HasForeignKey("BackgroundPictureId"); + + b.HasOne("WatchIt.Database.Model.Common.Gender", "Gender") + .WithMany() + .HasForeignKey("GenderId"); + + b.HasOne("WatchIt.Database.Model.Account.AccountProfilePicture", "ProfilePicture") + .WithOne("Account") + .HasForeignKey("WatchIt.Database.Model.Account.Account", "ProfilePictureId"); + + b.Navigation("BackgroundPicture"); + + b.Navigation("Gender"); + + b.Navigation("ProfilePicture"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountFollow", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "AccountFollowed") + .WithMany("AccountFollowers") + .HasForeignKey("AccountFollowedId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Account.Account", "AccountFollower") + .WithMany("AccountFollows") + .HasForeignKey("AccountFollowerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AccountFollowed"); + + b.Navigation("AccountFollower"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountRefreshToken", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("AccountRefreshTokens") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.Media", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPosterImage", "MediaPosterImage") + .WithOne("Media") + .HasForeignKey("WatchIt.Database.Model.Media.Media", "MediaPosterImageId"); + + b.Navigation("MediaPosterImage"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaGenre", b => + { + b.HasOne("WatchIt.Database.Model.Common.Genre", "Genre") + .WithMany("MediaGenres") + .HasForeignKey("GenreId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("MediaGenres") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Genre"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaMovie", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithOne() + .HasForeignKey("WatchIt.Database.Model.Media.MediaMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("MediaPhotoImages") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImageBackground", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaPhotoImage", "MediaPhotoImage") + .WithOne("MediaPhotoImageBackground") + .HasForeignKey("WatchIt.Database.Model.Media.MediaPhotoImageBackground", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaPhotoImage"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaProductionCountry", b => + { + b.HasOne("WatchIt.Database.Model.Common.Country", "Country") + .WithMany("MediaProductionCountries") + .HasForeignKey("CountryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("MediaProductionCountries") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Country"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithOne() + .HasForeignKey("WatchIt.Database.Model.Media.MediaSeries", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesEpisode", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaSeriesSeason", "MediaSeriesSeason") + .WithMany("MediaSeriesEpisodes") + .HasForeignKey("MediaSeriesSeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesSeason", b => + { + b.HasOne("WatchIt.Database.Model.Media.MediaSeries", "MediaSeries") + .WithMany("MediaSeriesSeasons") + .HasForeignKey("MediaSeriesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSeries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.Person", b => + { + b.HasOne("WatchIt.Database.Model.Common.Gender", "Gender") + .WithMany() + .HasForeignKey("GenderId"); + + b.HasOne("WatchIt.Database.Model.Person.PersonPhotoImage", "PersonPhoto") + .WithOne("Person") + .HasForeignKey("WatchIt.Database.Model.Person.Person", "PersonPhotoId"); + + b.Navigation("Gender"); + + b.Navigation("PersonPhoto"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRole", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("PersonActorRoles") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonActorRoleType", "PersonActorRoleType") + .WithMany() + .HasForeignKey("PersonActorRoleTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.Person", "Person") + .WithMany("PersonActorRoles") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Person"); + + b.Navigation("PersonActorRoleType"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRole", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("PersonCreatorRoles") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonCreatorRoleType", "PersonCreatorRoleType") + .WithMany() + .HasForeignKey("PersonCreatorRoleTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.Person", "Person") + .WithMany("PersonCreatorRoles") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + + b.Navigation("Person"); + + b.Navigation("PersonCreatorRoleType"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMedia", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingMedia") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("RatingMedia") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesEpisode", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingMediaSeriesEpisode") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.MediaSeriesEpisode", "MediaSeriesEpisode") + .WithMany("RatingMediaSeriesEpisode") + .HasForeignKey("MediaSeriesEpisodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("MediaSeriesEpisode"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingMediaSeriesSeason", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingMediaSeriesSeason") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Media.MediaSeriesSeason", "MediaSeriesSeason") + .WithMany("RatingMediaSeriesSeason") + .HasForeignKey("MediaSeriesSeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("MediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonActorRole", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingPersonActorRole") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonActorRole", "PersonActorRole") + .WithMany("RatingPersonActorRole") + .HasForeignKey("PersonActorRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("PersonActorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Rating.RatingPersonCreatorRole", b => + { + b.HasOne("WatchIt.Database.Model.Account.Account", "Account") + .WithMany("RatingPersonCreatorRole") + .HasForeignKey("AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("WatchIt.Database.Model.Person.PersonCreatorRole", "PersonCreatorRole") + .WithMany("RatingPersonCreatorRole") + .HasForeignKey("PersonCreatorRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Account"); + + b.Navigation("PersonCreatorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountMedia", b => + { + b.HasOne("WatchIt.Database.Model.Media.Media", "Media") + .WithMany("ViewCountsMedia") + .HasForeignKey("MediaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Media"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.ViewCount.ViewCountPerson", b => + { + b.HasOne("WatchIt.Database.Model.Person.Person", "Person") + .WithMany("ViewCountsPerson") + .HasForeignKey("PersonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Person"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => + { + b.Navigation("AccountFollowers"); + + b.Navigation("AccountFollows"); + + b.Navigation("AccountRefreshTokens"); + + b.Navigation("RatingMedia"); + + b.Navigation("RatingMediaSeriesEpisode"); + + b.Navigation("RatingMediaSeriesSeason"); + + b.Navigation("RatingPersonActorRole"); + + b.Navigation("RatingPersonCreatorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Account.AccountProfilePicture", b => + { + b.Navigation("Account") + .IsRequired(); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Country", b => + { + b.Navigation("MediaProductionCountries"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Common.Genre", b => + { + b.Navigation("MediaGenres"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.Media", b => + { + b.Navigation("MediaGenres"); + + b.Navigation("MediaPhotoImages"); + + b.Navigation("MediaProductionCountries"); + + b.Navigation("PersonActorRoles"); + + b.Navigation("PersonCreatorRoles"); + + b.Navigation("RatingMedia"); + + b.Navigation("ViewCountsMedia"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPhotoImage", b => + { + b.Navigation("MediaPhotoImageBackground"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaPosterImage", b => + { + b.Navigation("Media") + .IsRequired(); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeries", b => + { + b.Navigation("MediaSeriesSeasons"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesEpisode", b => + { + b.Navigation("RatingMediaSeriesEpisode"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Media.MediaSeriesSeason", b => + { + b.Navigation("MediaSeriesEpisodes"); + + b.Navigation("RatingMediaSeriesSeason"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.Person", b => + { + b.Navigation("PersonActorRoles"); + + b.Navigation("PersonCreatorRoles"); + + b.Navigation("ViewCountsPerson"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonActorRole", b => + { + b.Navigation("RatingPersonActorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonCreatorRole", b => + { + b.Navigation("RatingPersonCreatorRole"); + }); + + modelBuilder.Entity("WatchIt.Database.Model.Person.PersonPhotoImage", b => + { + b.Navigation("Person") + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.cs b/WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.cs new file mode 100644 index 0000000..6c093ea --- /dev/null +++ b/WatchIt.Database/WatchIt.Database/Migrations/20241109182449_RelationRename.cs @@ -0,0 +1,136 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace WatchIt.Database.Migrations +{ + /// + public partial class RelationRename : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AccountFollow_Accounts_AccountFollowedId", + table: "AccountFollow"); + + migrationBuilder.DropForeignKey( + name: "FK_AccountFollow_Accounts_AccountFollowerId", + table: "AccountFollow"); + + migrationBuilder.DropPrimaryKey( + name: "PK_AccountFollow", + table: "AccountFollow"); + + migrationBuilder.RenameTable( + name: "AccountFollow", + newName: "AccountFollows"); + + migrationBuilder.RenameIndex( + name: "IX_AccountFollow_Id", + table: "AccountFollows", + newName: "IX_AccountFollows_Id"); + + migrationBuilder.RenameIndex( + name: "IX_AccountFollow_AccountFollowerId", + table: "AccountFollows", + newName: "IX_AccountFollows_AccountFollowerId"); + + migrationBuilder.RenameIndex( + name: "IX_AccountFollow_AccountFollowedId", + table: "AccountFollows", + newName: "IX_AccountFollows_AccountFollowedId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_AccountFollows", + table: "AccountFollows", + column: "Id"); + + migrationBuilder.UpdateData( + table: "Accounts", + keyColumn: "Id", + keyValue: 1L, + columns: new[] { "LeftSalt", "Password", "RightSalt" }, + values: new object[] { "QkJky0:m43g!mRL_-0S'", new byte[] { 104, 21, 33, 198, 192, 7, 229, 80, 195, 46, 190, 26, 125, 243, 113, 195, 194, 9, 145, 142, 56, 34, 125, 141, 133, 113, 14, 172, 29, 90, 194, 60, 98, 40, 121, 132, 218, 157, 80, 128, 70, 136, 201, 208, 36, 37, 124, 215, 144, 242, 212, 68, 209, 27, 248, 191, 212, 84, 250, 35, 230, 51, 218, 15 }, "~-jO$aMa{Q9lAW~>)Z+Z" }); + + migrationBuilder.AddForeignKey( + name: "FK_AccountFollows_Accounts_AccountFollowedId", + table: "AccountFollows", + column: "AccountFollowedId", + principalTable: "Accounts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_AccountFollows_Accounts_AccountFollowerId", + table: "AccountFollows", + column: "AccountFollowerId", + principalTable: "Accounts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_AccountFollows_Accounts_AccountFollowedId", + table: "AccountFollows"); + + migrationBuilder.DropForeignKey( + name: "FK_AccountFollows_Accounts_AccountFollowerId", + table: "AccountFollows"); + + migrationBuilder.DropPrimaryKey( + name: "PK_AccountFollows", + table: "AccountFollows"); + + migrationBuilder.RenameTable( + name: "AccountFollows", + newName: "AccountFollow"); + + migrationBuilder.RenameIndex( + name: "IX_AccountFollows_Id", + table: "AccountFollow", + newName: "IX_AccountFollow_Id"); + + migrationBuilder.RenameIndex( + name: "IX_AccountFollows_AccountFollowerId", + table: "AccountFollow", + newName: "IX_AccountFollow_AccountFollowerId"); + + migrationBuilder.RenameIndex( + name: "IX_AccountFollows_AccountFollowedId", + table: "AccountFollow", + newName: "IX_AccountFollow_AccountFollowedId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_AccountFollow", + table: "AccountFollow", + column: "Id"); + + migrationBuilder.UpdateData( + table: "Accounts", + keyColumn: "Id", + keyValue: 1L, + columns: new[] { "LeftSalt", "Password", "RightSalt" }, + values: new object[] { "sfA:fW!3D=GbwXn]X+rm", new byte[] { 95, 134, 48, 126, 85, 131, 129, 152, 252, 161, 69, 133, 62, 112, 45, 111, 3, 163, 80, 99, 167, 66, 169, 121, 140, 69, 242, 14, 89, 126, 184, 43, 62, 87, 22, 1, 88, 246, 34, 181, 231, 110, 14, 54, 120, 114, 37, 67, 240, 82, 112, 125, 84, 155, 194, 90, 14, 189, 90, 68, 30, 146, 204, 105 }, "@$rr>fSvr5Ls|D+Wp;?D" }); + + migrationBuilder.AddForeignKey( + name: "FK_AccountFollow_Accounts_AccountFollowedId", + table: "AccountFollow", + column: "AccountFollowedId", + principalTable: "Accounts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_AccountFollow_Accounts_AccountFollowerId", + table: "AccountFollow", + column: "AccountFollowerId", + principalTable: "Accounts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs b/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs index a388421..d0c9b33 100644 --- a/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs +++ b/WatchIt.Database/WatchIt.Database/Migrations/DatabaseContextModelSnapshot.cs @@ -108,9 +108,9 @@ namespace WatchIt.Database.Migrations Email = "root@watch.it", IsAdmin = true, LastActive = new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), - LeftSalt = "sfA:fW!3D=GbwXn]X+rm", - Password = new byte[] { 95, 134, 48, 126, 85, 131, 129, 152, 252, 161, 69, 133, 62, 112, 45, 111, 3, 163, 80, 99, 167, 66, 169, 121, 140, 69, 242, 14, 89, 126, 184, 43, 62, 87, 22, 1, 88, 246, 34, 181, 231, 110, 14, 54, 120, 114, 37, 67, 240, 82, 112, 125, 84, 155, 194, 90, 14, 189, 90, 68, 30, 146, 204, 105 }, - RightSalt = "@$rr>fSvr5Ls|D+Wp;?D", + LeftSalt = "QkJky0:m43g!mRL_-0S'", + Password = new byte[] { 104, 21, 33, 198, 192, 7, 229, 80, 195, 46, 190, 26, 125, 243, 113, 195, 194, 9, 145, 142, 56, 34, 125, 141, 133, 113, 14, 172, 29, 90, 194, 60, 98, 40, 121, 132, 218, 157, 80, 128, 70, 136, 201, 208, 36, 37, 124, 215, 144, 242, 212, 68, 209, 27, 248, 191, 212, 84, 250, 35, 230, 51, 218, 15 }, + RightSalt = "~-jO$aMa{Q9lAW~>)Z+Z", Username = "root" }); }); @@ -136,7 +136,7 @@ namespace WatchIt.Database.Migrations b.HasIndex("Id") .IsUnique(); - b.ToTable("AccountFollow"); + b.ToTable("AccountFollows"); }); modelBuilder.Entity("WatchIt.Database.Model.Account.AccountProfilePicture", b => @@ -1020,7 +1020,7 @@ namespace WatchIt.Database.Migrations modelBuilder.Entity("WatchIt.Database.Model.Account.AccountFollow", b => { b.HasOne("WatchIt.Database.Model.Account.Account", "AccountFollowed") - .WithMany("AccountFollowedBy") + .WithMany("AccountFollowers") .HasForeignKey("AccountFollowedId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); @@ -1348,7 +1348,7 @@ namespace WatchIt.Database.Migrations modelBuilder.Entity("WatchIt.Database.Model.Account.Account", b => { - b.Navigation("AccountFollowedBy"); + b.Navigation("AccountFollowers"); b.Navigation("AccountFollows"); diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs index a57a424..e556d81 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Controllers/AccountsController.cs @@ -135,6 +135,8 @@ public class AccountsController(IAccountsControllerService accountsControllerSer #endregion + #region Media + [HttpGet("{id}/movies")] [AllowAnonymous] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] @@ -152,4 +154,35 @@ public class AccountsController(IAccountsControllerService accountsControllerSer [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetAccountRatedPersons([FromRoute]long id, PersonRatedQueryParameters query) => await accountsControllerService.GetAccountRatedPersons(id, query); + + #endregion + + #region Follows + + [HttpGet("{id}/follows")] + [AllowAnonymous] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetAccountFollows([FromRoute]long id, AccountQueryParameters query) => await accountsControllerService.GetAccountFollows(id, query); + + [HttpGet("{id}/followers")] + [AllowAnonymous] + [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetAccountFollowers([FromRoute]long id, AccountQueryParameters query) => await accountsControllerService.GetAccountFollowers(id, query); + + [HttpPost("follows/{user_id}")] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + public async Task PostAccountFollow([FromRoute(Name = "user_id")]long userId) => await accountsControllerService.PostAccountFollow(userId); + + [HttpDelete("follows/{user_id}")] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)] + public async Task DeleteAccountFollow([FromRoute(Name = "user_id")]long userId) => await accountsControllerService.DeleteAccountFollow(userId); + + #endregion } \ No newline at end of file diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs index 14fc4ba..b6c75c6 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/AccountsControllerService.cs @@ -319,6 +319,8 @@ public class AccountsControllerService( #endregion + #region Media + public async Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query) { Account? account = await database.Accounts.FirstOrDefaultAsync(x => x.Id == id); @@ -362,6 +364,79 @@ public class AccountsControllerService( response = query.PrepareData(response); return RequestResult.Ok(response); } + + #endregion + + #region Follows + + public async Task GetAccountFollows(long id, AccountQueryParameters query) + { + Account? account = await database.Accounts.FirstOrDefaultAsync(x => x.Id == id); + if (account is null) + { + return RequestResult.NotFound(); + } + + IEnumerable data = account.AccountFollows.Select(x => new AccountResponse(x.AccountFollowed)); + data = query.PrepareData(data); + return RequestResult.Ok(data); + } + + public async Task GetAccountFollowers(long id, AccountQueryParameters query) + { + Account? account = await database.Accounts.FirstOrDefaultAsync(x => x.Id == id); + if (account is null) + { + return RequestResult.NotFound(); + } + + IEnumerable data = account.AccountFollowers.Select(x => new AccountResponse(x.AccountFollower)); + data = query.PrepareData(data); + return RequestResult.Ok(data); + } + + public async Task PostAccountFollow(long userId) + { + long followerId = userService.GetUserId(); + if (userId == followerId) + { + return RequestResult.BadRequest().AddValidationError("user_id", "You cannot follow yourself"); + } + if (!database.Accounts.Any(x => x.Id == userId)) + { + return RequestResult.BadRequest().AddValidationError("user_id", "User with this id doesn't exist"); + } + + Account account = await database.Accounts.FirstAsync(x => x.Id == followerId); + if (account.AccountFollows.All(x => x.AccountFollowedId != userId)) + { + AccountFollow follow = new AccountFollow() + { + AccountFollowerId = followerId, + AccountFollowedId = userId, + }; + await database.AccountFollows.AddAsync(follow); + await database.SaveChangesAsync(); + } + + return RequestResult.Ok(); + } + + public async Task DeleteAccountFollow(long userId) + { + AccountFollow? accountFollow = await database.AccountFollows.FirstOrDefaultAsync(x => x.AccountFollowerId == userService.GetUserId() && x.AccountFollowedId == userId); + + if (accountFollow is not null) + { + database.AccountFollows.Attach(accountFollow); + database.AccountFollows.Remove(accountFollow); + await database.SaveChangesAsync(); + } + + return RequestResult.Ok(); + } + + #endregion #endregion diff --git a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs index bb03dc5..9e51d77 100644 --- a/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs +++ b/WatchIt.WebAPI/WatchIt.WebAPI.Services/WatchIt.WebAPI.Services.Controllers/WatchIt.WebAPI.Services.Controllers.Accounts/IAccountsControllerService.cs @@ -28,4 +28,8 @@ public interface IAccountsControllerService Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query); Task GetAccountRatedSeries(long id, SeriesRatedQueryParameters query); Task GetAccountRatedPersons(long id, PersonRatedQueryParameters query); + Task GetAccountFollows(long id, AccountQueryParameters query); + Task GetAccountFollowers(long id, AccountQueryParameters query); + Task PostAccountFollow(long userId); + Task DeleteAccountFollow(long userId); } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs index df8649f..0be0807 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/AccountsClientService.cs @@ -13,6 +13,36 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig { #region PUBLIC METHODS + #region Main + + public async Task GetAccounts(AccountQueryParameters? query = null, Action>? successAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.GetAccounts); + HttpRequest request = new HttpRequest(HttpMethodType.Get, url) + { + Query = query + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .ExecuteAction(); + } + + public async Task GetAccount(long id, Action? successAction = null, Action? notFoundAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.GetAccount, id); + HttpRequest request = new HttpRequest(HttpMethodType.Get, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor404NotFound(notFoundAction) + .ExecuteAction(); + } + + #endregion + + #region Authentication + public async Task Register(RegisterRequest data, Action? createdAction = null, Action>? badRequestAction = null) { string url = GetUrl(EndpointsConfiguration.Accounts.Register); @@ -69,7 +99,11 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig response.RegisterActionFor2XXSuccess(successAction) .ExecuteAction(); } + + #endregion + #region Profile picture + public async Task GetAccountProfilePicture(long id, Action? successAction = null, Action>? badRequestAction = null, Action? notFoundAction = null) { string url = GetUrl(EndpointsConfiguration.Accounts.GetAccountProfilePicture, id); @@ -109,7 +143,11 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig .RegisterActionFor401Unauthorized(unauthorizedAction) .ExecuteAction(); } - + + #endregion + + #region Profile background + public async Task GetAccountProfileBackground(long id, Action? successAction = null, Action>? badRequestAction = null, Action? notFoundAction = null) { string url = GetUrl(EndpointsConfiguration.Accounts.GetAccountProfileBackground, id); @@ -150,29 +188,9 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig .ExecuteAction(); } - public async Task GetAccounts(AccountQueryParameters query, Action>? successAction = null) - { - string url = GetUrl(EndpointsConfiguration.Accounts.GetAccounts); - HttpRequest request = new HttpRequest(HttpMethodType.Get, url) - { - Query = query - }; - - HttpResponse response = await httpClientService.SendRequestAsync(request); - response.RegisterActionFor2XXSuccess(successAction) - .ExecuteAction(); - } + #endregion - public async Task GetAccount(long id, Action? successAction = null, Action? notFoundAction = null) - { - string url = GetUrl(EndpointsConfiguration.Accounts.GetAccount, id); - HttpRequest request = new HttpRequest(HttpMethodType.Get, url); - - HttpResponse response = await httpClientService.SendRequestAsync(request); - response.RegisterActionFor2XXSuccess(successAction) - .RegisterActionFor404NotFound(notFoundAction) - .ExecuteAction(); - } + #region Account management public async Task PutAccountProfileInfo(AccountProfileInfoRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null) { @@ -234,6 +252,10 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig .ExecuteAction(); } + #endregion + + #region Media + public async Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null) { string url = GetUrl(EndpointsConfiguration.Accounts.GetAccountRatedMovies, id); @@ -275,6 +297,63 @@ public class AccountsClientService(IHttpClientService httpClientService, IConfig .RegisterActionFor404NotFound(notFoundAction) .ExecuteAction(); } + + #endregion + + #region Follows + + public async Task GetAccountFollows(long id, AccountQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.GetAccountFollows, id); + HttpRequest request = new HttpRequest(HttpMethodType.Get, url) + { + Query = query + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor404NotFound(notFoundAction) + .ExecuteAction(); + } + + public async Task GetAccountFollowers(long id, AccountQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.GetAccountFollowers, id); + HttpRequest request = new HttpRequest(HttpMethodType.Get, url) + { + Query = query + }; + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor404NotFound(notFoundAction) + .ExecuteAction(); + } + + public async Task PostAccountFollow(long userId, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.PostAccountFollow, userId); + HttpRequest request = new HttpRequest(HttpMethodType.Post, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor400BadRequest(badRequestAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .ExecuteAction(); + } + + public async Task DeleteAccountFollow(long userId, Action? successAction = null, Action? unauthorizedAction = null) + { + string url = GetUrl(EndpointsConfiguration.Accounts.DeleteAccountFollow, userId); + HttpRequest request = new HttpRequest(HttpMethodType.Delete, url); + + HttpResponse response = await httpClientService.SendRequestAsync(request); + response.RegisterActionFor2XXSuccess(successAction) + .RegisterActionFor401Unauthorized(unauthorizedAction) + .ExecuteAction(); + } + + #endregion #endregion diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs index 09543c6..7300a14 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Client/Accounts/IAccountsClientService.cs @@ -18,13 +18,17 @@ public interface IAccountsClientService Task GetAccountProfileBackground(long id, Action? successAction = null, Action>? badRequestAction = null, Action? notFoundAction = null); Task PutAccountProfileBackground(AccountProfileBackgroundRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); Task DeleteAccountProfileBackground(Action? successAction = null, Action? unauthorizedAction = null); - Task GetAccounts(AccountQueryParameters query, Action>? successAction = null); + Task GetAccounts(AccountQueryParameters? query = null, Action>? successAction = null); Task GetAccount(long id, Action? successAction = null, Action? notFoundAction = null); Task PutAccountProfileInfo(AccountProfileInfoRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); Task PatchAccountUsername(AccountUsernameRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); Task PatchAccountEmail(AccountEmailRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); Task PatchAccountPassword(AccountPasswordRequest data, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); - Task GetAccountRatedMovies(long id, MovieRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null); - Task GetAccountRatedSeries(long id, SeriesRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null); - Task GetAccountRatedPersons(long id, PersonRatedQueryParameters query, Action>? successAction = null, Action? notFoundAction = null); + Task GetAccountRatedMovies(long id, MovieRatedQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null); + Task GetAccountRatedSeries(long id, SeriesRatedQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null); + Task GetAccountRatedPersons(long id, PersonRatedQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null); + Task GetAccountFollows(long id, AccountQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null); + Task GetAccountFollowers(long id, AccountQueryParameters? query = null, Action>? successAction = null, Action? notFoundAction = null); + Task PostAccountFollow(long userId, Action? successAction = null, Action>? badRequestAction = null, Action? unauthorizedAction = null); + Task DeleteAccountFollow(long userId, Action? successAction = null, Action? unauthorizedAction = null); } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs index eae345a..9793d7b 100644 --- a/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs +++ b/WatchIt.Website/WatchIt.Website.Services/WatchIt.Website.Services.Configuration/Model/Accounts.cs @@ -22,4 +22,8 @@ public class Accounts public string GetAccountRatedMovies { get; set; } public string GetAccountRatedSeries { get; set; } public string GetAccountRatedPersons { get; set; } + public string GetAccountFollows { get; set; } + public string GetAccountFollowers { get; set; } + public string PostAccountFollow { get; set; } + public string DeleteAccountFollow { get; set; } } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/App.razor b/WatchIt.Website/WatchIt.Website/App.razor index f460abd..7dc152c 100644 --- a/WatchIt.Website/WatchIt.Website/App.razor +++ b/WatchIt.Website/WatchIt.Website/App.razor @@ -9,7 +9,7 @@ - + diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Common/Subcomponents/UserListItemComponent.razor similarity index 80% rename from WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor rename to WatchIt.Website/WatchIt.Website/Components/Common/Subcomponents/UserListItemComponent.razor index dc936c9..771575a 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor +++ b/WatchIt.Website/WatchIt.Website/Components/Common/Subcomponents/UserListItemComponent.razor @@ -1,7 +1,7 @@
+ Size="@(PictureSize)"/>

@(Item.Username)

\ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Common/Subcomponents/UserListItemComponent.razor.cs similarity index 51% rename from WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor.cs rename to WatchIt.Website/WatchIt.Website/Components/Common/Subcomponents/UserListItemComponent.razor.cs index b81a075..a96df02 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Subcomponents/UserSearchResultItemComponent.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Components/Common/Subcomponents/UserListItemComponent.razor.cs @@ -1,13 +1,14 @@ using Microsoft.AspNetCore.Components; using WatchIt.Common.Model.Accounts; -namespace WatchIt.Website.Components.Pages.SearchPage.Subcomponents; +namespace WatchIt.Website.Components.Common.Subcomponents; -public partial class UserSearchResultItemComponent : ComponentBase +public partial class UserListItemComponent : ComponentBase { #region PROPERTIES [Parameter] public required AccountResponse Item { get; set; } + [Parameter] public int PictureSize { get; set; } = 90; #endregion } \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Panels/UsersSearchResultPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Panels/UsersSearchResultPanelComponent.razor index cb5dd8e..af69ba3 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Panels/UsersSearchResultPanelComponent.razor +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/SearchPage/Panels/UsersSearchResultPanelComponent.razor @@ -1,5 +1,4 @@ @using Blazorise.Extensions -@using WatchIt.Website.Components.Pages.SearchPage.Subcomponents @@ -29,7 +28,7 @@ @{ int iCopy = i; } - + } diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor new file mode 100644 index 0000000..db95930 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor @@ -0,0 +1,29 @@ +
+
+

@(Title)

+
+ @if (!_loaded) + { +
+ +
+ } + else if (!_items.Any()) + { +
+
+ No items +
+
+ } + else + { + foreach (AccountResponse item in _items) + { +
+ +
+ } + } +
\ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor.cs new file mode 100644 index 0000000..8cf1cc8 --- /dev/null +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/FollowListPanelComponent.razor.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Components; +using WatchIt.Common.Model.Accounts; + +namespace WatchIt.Website.Components.Pages.UserPage.Panels; + +public partial class FollowListPanelComponent : ComponentBase +{ + #region PARAMETERS + + [Parameter] public required string Title { get; set; } + [Parameter] public required Func>, Task> DownloadItemsMethod { get; set; } + + #endregion + + + + #region FIELDS + + private bool _loaded; + + private List _items = []; + + #endregion + + + + #region PRIVATE METHODS + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await DownloadItemsMethod.Invoke(data => _items.AddRange(data)); + + _loaded = true; + StateHasChanged(); + } + } + + #endregion +} \ No newline at end of file diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor index 28059b2..35214d5 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor @@ -1,29 +1,49 @@
- +
-

@(AccountProfileInfoData.Username)

+

@(Data.Username)

- @if (!string.IsNullOrWhiteSpace(AccountProfileInfoData.Description)) + @if (!string.IsNullOrWhiteSpace(Data.Description)) { - @(AccountProfileInfoData.Description) + @(Data.Description) }
diff --git a/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor.cs b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor.cs index a7d9ecd..f928b3f 100644 --- a/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Components/Pages/UserPage/Panels/UserPageHeaderPanelComponent.razor.cs @@ -9,7 +9,6 @@ public partial class UserPageHeaderPanelComponent : ComponentBase { #region SERVICES - [Inject] private IAuthenticationService AuthenticationService { get; set; } = default!; [Inject] private IAccountsClientService AccountsClientService { get; set; } = default!; #endregion @@ -18,38 +17,45 @@ public partial class UserPageHeaderPanelComponent : ComponentBase #region PARAMETERS - [Parameter] public required AccountResponse AccountProfileInfoData { get; set; } + [Parameter] public required AccountResponse Data { get; set; } + [Parameter] public required List Followers { get; set; } + [Parameter] public AccountResponse? LoggedUserData { get; set; } + [Parameter] public Action? FollowingChanged { get; set; } #endregion #region FIELDS + + private bool _followLoading; - private AccountProfilePictureResponse? _accountProfilePicture; - #endregion - - - + + + #region PRIVATE METHODS - protected override async Task OnAfterRenderAsync(bool firstRender) + private async Task Follow() { - if (firstRender) + _followLoading = true; + if (Followers.Any(x => x.Id == LoggedUserData!.Id)) { - List endTasks = new List(); - - // STEP 0 - endTasks.AddRange( - [ - AccountsClientService.GetAccountProfilePicture(AccountProfileInfoData.Id, data => _accountProfilePicture = data), - ]); - - // END - await Task.WhenAll(endTasks); - - StateHasChanged(); + await AccountsClientService.DeleteAccountFollow(Data.Id, () => + { + Followers.RemoveAll(x => x.Id == LoggedUserData!.Id); + FollowingChanged?.Invoke(false); + _followLoading = false; + }); + } + else + { + await AccountsClientService.PostAccountFollow(Data.Id, () => + { + Followers.Add(LoggedUserData); + FollowingChanged?.Invoke(true); + _followLoading = false; + }); } } diff --git a/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor b/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor index 722e501..94f5a6e 100644 --- a/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor +++ b/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor @@ -48,10 +48,12 @@ {
- +
-
+
Movies TV Series People + Follows + Followers @@ -160,22 +164,34 @@ PictureDownloadingTask="@((id, action) => PersonsClientService.GetPersonPhoto(id, action))" ItemDownloadingTask="@((query, action) => AccountsClientService.GetAccountRatedPersons(_accountData.Id, query, action))" SortingOptions="@(new Dictionary - { - { "user_rating.average", "Average user rating" }, - { "user_rating.count", "Number of user ratings" }, - { "user_rating_last_date", "User rating date" }, - { "rating.average", "Average rating" }, - { "rating.count", "Number of ratings" }, - { "name", "Name" }, - { "birth_date", "Birth date" }, - { "death_date", "Death date" }, - })" + { + { "user_rating.average", "Average user rating" }, + { "user_rating.count", "Number of user ratings" }, + { "user_rating_last_date", "User rating date" }, + { "rating.average", "Average rating" }, + { "rating.count", "Number of ratings" }, + { "name", "Name" }, + { "birth_date", "Birth date" }, + { "death_date", "Death date" }, + })" PosterPlaceholder="/assets/person_poster.png" GetGlobalRatingMethod="@((id, action) => PersonsClientService.GetPersonGlobalRating(id, action))">
+ +
+ +
+
+ +
+ +
+
diff --git a/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor.cs b/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor.cs index 41cec0a..de0c490 100644 --- a/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor.cs +++ b/WatchIt.Website/WatchIt.Website/Pages/UserPage.razor.cs @@ -38,7 +38,11 @@ public partial class UserPage : ComponentBase private bool _loaded; private bool _redirection; private bool _owner; + private User? _user; + + private AccountResponse? _loggedUserData; private AccountResponse? _accountData; + private List _followers; #endregion @@ -66,8 +70,13 @@ public partial class UserPage : ComponentBase await Task.WhenAll(step1Tasks); endTasks.AddRange( [ - AccountsClientService.GetAccountProfileBackground(_accountData.Id, data => Layout.BackgroundPhoto = data) + AccountsClientService.GetAccountProfileBackground(_accountData.Id, data => Layout.BackgroundPhoto = data), + AccountsClientService.GetAccountFollowers(_accountData.Id, successAction: data => _followers = data.ToList()) ]); + if (_user is not null) + { + endTasks.Add(AccountsClientService.GetAccount(_user.Id, data => _loggedUserData = data)); + } // END await Task.WhenAll(endTasks); @@ -79,20 +88,20 @@ public partial class UserPage : ComponentBase private async Task GetUserData() { - User? user = await AuthenticationService.GetUserAsync(); + _user = await AuthenticationService.GetUserAsync(); if (!Id.HasValue) { - if (user is null) + if (_user is null) { NavigationManager.NavigateTo($"/auth?redirect_to={WebUtility.UrlEncode("/user")}"); _redirection = true; return; } - Id = user.Id; + Id = _user.Id; } await AccountsClientService.GetAccount(Id.Value, data => _accountData = data); - _owner = Id.Value == user?.Id; + _owner = Id.Value == _user?.Id; } diff --git a/WatchIt.Website/WatchIt.Website/appsettings.json b/WatchIt.Website/WatchIt.Website/appsettings.json index 72afefa..ba6fad3 100644 --- a/WatchIt.Website/WatchIt.Website/appsettings.json +++ b/WatchIt.Website/WatchIt.Website/appsettings.json @@ -35,7 +35,11 @@ "PatchAccountPassword": "/password", "GetAccountRatedMovies": "/{0}/movies", "GetAccountRatedSeries": "/{0}/series", - "GetAccountRatedPersons": "/{0}/persons" + "GetAccountRatedPersons": "/{0}/persons", + "GetAccountFollows": "/{0}/follows", + "GetAccountFollowers": "/{0}/followers", + "PostAccountFollow": "/follows/{0}", + "DeleteAccountFollow": "/follows/{0}" }, "Genders": { "Base": "/genders", diff --git a/WatchIt.Website/WatchIt.Website/wwwroot/css/general.css b/WatchIt.Website/WatchIt.Website/wwwroot/css/general.css index 319ee59..5cc54b1 100644 --- a/WatchIt.Website/WatchIt.Website/wwwroot/css/general.css +++ b/WatchIt.Website/WatchIt.Website/wwwroot/css/general.css @@ -66,6 +66,11 @@ body, html { gap: 1rem; } +.metadata-pill-hoverable:hover { + background-color: gray; + color: black; +} +