diff --git a/api/src/Kurs.Platform.Application.Contracts/Blog/BlogCategoryDto.cs b/api/src/Kurs.Platform.Application.Contracts/Blog/BlogCategoryDto.cs new file mode 100644 index 00000000..367cd6dd --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Blog/BlogCategoryDto.cs @@ -0,0 +1,26 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Kurs.Platform.Blog +{ + public class BlogCategoryDto : FullAuditedEntityDto + { + public string Name { get; set; } + public string Slug { get; set; } + public string Description { get; set; } + public string Icon { get; set; } + public int DisplayOrder { get; set; } + public bool IsActive { get; set; } + public int PostCount { get; set; } + } + + public class CreateUpdateBlogCategoryDto + { + public string Name { get; set; } + public string Slug { get; set; } + public string Description { get; set; } + public string Icon { get; set; } + public int DisplayOrder { get; set; } + public bool IsActive { get; set; } + } +} diff --git a/api/src/Kurs.Platform.Application.Contracts/Blog/BlogPostDto.cs b/api/src/Kurs.Platform.Application.Contracts/Blog/BlogPostDto.cs new file mode 100644 index 00000000..362ed010 --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Blog/BlogPostDto.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace Kurs.Platform.Blog +{ + public class BlogPostDto : FullAuditedEntityDto + { + public string Title { get; set; } + public string Slug { get; set; } + public string Content { get; set; } + public string Summary { get; set; } + public string CoverImage { get; set; } + + public Guid CategoryId { get; set; } + public BlogCategoryDto Category { get; set; } + + public AuthorDto Author { get; set; } + + public int ViewCount { get; set; } + public int LikeCount { get; set; } + public int CommentCount { get; set; } + + public bool IsPublished { get; set; } + public DateTime? PublishedAt { get; set; } + + public List Tags { get; set; } + public bool IsLiked { get; set; } + + public BlogPostDto() + { + Tags = new List(); + } + } + + public class AuthorDto + { + public Guid Id { get; set; } + public string Name { get; set; } + public string Avatar { get; set; } + } + + public class CreateUpdateBlogPostDto + { + public string Title { get; set; } + public string Slug { get; set; } + public string Content { get; set; } + public string Summary { get; set; } + public string CoverImage { get; set; } + public Guid CategoryId { get; set; } + public List Tags { get; set; } + public bool IsPublished { get; set; } + + public CreateUpdateBlogPostDto() + { + Tags = new List(); + } + } + + public class BlogPostListDto : EntityDto + { + public string Title { get; set; } + public string Slug { get; set; } + public string Summary { get; set; } + public string CoverImage { get; set; } + + public BlogCategoryDto Category { get; set; } + public AuthorDto Author { get; set; } + + public int ViewCount { get; set; } + public int LikeCount { get; set; } + public int CommentCount { get; set; } + + public bool IsPublished { get; set; } + public DateTime? PublishedAt { get; set; } + public DateTime CreatedAt { get; set; } + + public List Tags { get; set; } + + public BlogPostListDto() + { + Tags = new List(); + } + } +} diff --git a/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs b/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs new file mode 100644 index 00000000..cf83be36 --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Blog/IBlogAppService.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace Kurs.Platform.Blog +{ + public interface IBlogAppService : IApplicationService + { + // Blog Post methods + Task> GetPostsAsync(GetBlogPostsInput input); + Task GetPostAsync(Guid id); + Task GetPostBySlugAsync(string slug); + Task CreatePostAsync(CreateUpdateBlogPostDto input); + Task UpdatePostAsync(Guid id, CreateUpdateBlogPostDto input); + Task DeletePostAsync(Guid id); + Task PublishPostAsync(Guid id); + Task UnpublishPostAsync(Guid id); + Task LikePostAsync(Guid id); + Task UnlikePostAsync(Guid id); + Task IncrementViewCountAsync(Guid id); + + // Blog Category methods + Task> GetCategoriesAsync(); + Task GetCategoryAsync(Guid id); + Task CreateCategoryAsync(CreateUpdateBlogCategoryDto input); + Task UpdateCategoryAsync(Guid id, CreateUpdateBlogCategoryDto input); + Task DeleteCategoryAsync(Guid id); + + // Search and filters + Task> SearchPostsAsync(SearchBlogPostsInput input); + Task> GetPostsByCategoryAsync(Guid categoryId, PagedAndSortedResultRequestDto input); + Task> GetPostsByTagAsync(string tag, PagedAndSortedResultRequestDto input); + Task> GetPostsByAuthorAsync(Guid authorId, PagedAndSortedResultRequestDto input); + + // Tags + Task> GetPopularTagsAsync(int count = 20); + + // Stats + Task GetStatsAsync(); + } + + public class GetBlogPostsInput : PagedAndSortedResultRequestDto + { + public string Filter { get; set; } + public Guid? CategoryId { get; set; } + public string Tag { get; set; } + public Guid? AuthorId { get; set; } + public bool? IsPublished { get; set; } + public string SortBy { get; set; } = "latest"; // latest, popular, trending + } + + public class SearchBlogPostsInput : PagedAndSortedResultRequestDto + { + public string Query { get; set; } + public Guid? CategoryId { get; set; } + public string Tag { get; set; } + public Guid? AuthorId { get; set; } + public bool? IsPublished { get; set; } + } + + public class BlogStatsDto + { + public int TotalPosts { get; set; } + public int PublishedPosts { get; set; } + public int DraftPosts { get; set; } + public int TotalCategories { get; set; } + public int TotalViews { get; set; } + public int TotalLikes { get; set; } + public int TotalComments { get; set; } + public List PopularTags { get; set; } + public BlogPostListDto LatestPost { get; set; } + public BlogPostListDto MostViewedPost { get; set; } + + public BlogStatsDto() + { + PopularTags = new List(); + } + } +} diff --git a/api/src/Kurs.Platform.Application.Contracts/Forum/ForumCategoryDto.cs b/api/src/Kurs.Platform.Application.Contracts/Forum/ForumCategoryDto.cs new file mode 100644 index 00000000..dda837fe --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Forum/ForumCategoryDto.cs @@ -0,0 +1,34 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace Kurs.Platform.Forum +{ + public class ForumCategoryDto : FullAuditedEntityDto + { + public string Name { get; set; } + public string Slug { get; set; } + public string Description { get; set; } + public string Icon { get; set; } + public int DisplayOrder { get; set; } + public bool IsActive { get; set; } + public bool IsLocked { get; set; } + + public int TopicCount { get; set; } + public int PostCount { get; set; } + + public Guid? LastPostId { get; set; } + public DateTime? LastPostDate { get; set; } + public string LastPostUserName { get; set; } + } + + public class CreateUpdateForumCategoryDto + { + public string Name { get; set; } + public string Slug { get; set; } + public string Description { get; set; } + public string Icon { get; set; } + public int DisplayOrder { get; set; } + public bool IsActive { get; set; } + public bool IsLocked { get; set; } + } +} diff --git a/api/src/Kurs.Platform.Application.Contracts/Forum/ForumPostDto.cs b/api/src/Kurs.Platform.Application.Contracts/Forum/ForumPostDto.cs new file mode 100644 index 00000000..5ce2970d --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Forum/ForumPostDto.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace Kurs.Platform.Forum +{ + public class ForumPostDto : FullAuditedEntityDto + { + public Guid? TopicId { get; set; } + public Guid? CategoryId { get; set; } + public string Title { get; set; } + public string Content { get; set; } + public Guid AuthorId { get; set; } + public AuthorDto Author { get; set; } + public Guid? ParentId { get; set; } + public int LikeCount { get; set; } + public int ViewCount { get; set; } + public int ReplyCount { get; set; } + public bool IsLiked { get; set; } + public bool IsBestAnswer { get; set; } + public bool IsEdited { get; set; } + public DateTime? EditedAt { get; set; } + public List Tags { get; set; } + public LastReplyDto LastReply { get; set; } + public List Replies { get; set; } + } + + public class CreatePostRequest + { + public Guid? TopicId { get; set; } + public Guid? CategoryId { get; set; } + public string Title { get; set; } + public string Content { get; set; } + public Guid? ParentId { get; set; } + public List Tags { get; set; } + } + + public class LastReplyDto + { + public Guid Id { get; set; } + public AuthorDto Author { get; set; } + public DateTime CreationTime { get; set; } + } +} diff --git a/api/src/Kurs.Platform.Application.Contracts/Forum/ForumTopicDto.cs b/api/src/Kurs.Platform.Application.Contracts/Forum/ForumTopicDto.cs new file mode 100644 index 00000000..54144414 --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Forum/ForumTopicDto.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace Kurs.Platform.Forum +{ + public class ForumTopicDto : FullAuditedEntityDto + { + public string Title { get; set; } + public string Content { get; set; } + + public Guid CategoryId { get; set; } + public ForumCategoryDto Category { get; set; } + + public AuthorDto Author { get; set; } + + public int ViewCount { get; set; } + public int ReplyCount { get; set; } + public int LikeCount { get; set; } + + public bool IsPinned { get; set; } + public bool IsLocked { get; set; } + public bool IsSolved { get; set; } + + public Guid? LastPostId { get; set; } + public DateTime? LastPostDate { get; set; } + public string LastPostUserName { get; set; } + + public List Tags { get; set; } + public bool IsLiked { get; set; } + + public ForumTopicDto() + { + Tags = new List(); + } + } + + public class AuthorDto + { + public Guid Id { get; set; } + public string Name { get; set; } + public string Avatar { get; set; } + } + + public class CreateForumTopicDto + { + public string Title { get; set; } + public string Content { get; set; } + public Guid CategoryId { get; set; } + public List Tags { get; set; } + + public CreateForumTopicDto() + { + Tags = new List(); + } + } + + public class UpdateForumTopicDto + { + public string Title { get; set; } + public string Content { get; set; } + public List Tags { get; set; } + + public UpdateForumTopicDto() + { + Tags = new List(); + } + } + + public class ForumTopicListDto : EntityDto + { + public string Title { get; set; } + public Guid CategoryId { get; set; } + public string CategoryName { get; set; } + + public AuthorDto Author { get; set; } + + public int ViewCount { get; set; } + public int ReplyCount { get; set; } + public int LikeCount { get; set; } + + public bool IsPinned { get; set; } + public bool IsLocked { get; set; } + public bool IsSolved { get; set; } + + public DateTime? LastPostDate { get; set; } + public string LastPostUserName { get; set; } + + public DateTime CreatedAt { get; set; } + + public List Tags { get; set; } + + public ForumTopicListDto() + { + Tags = new List(); + } + } + + public class ForumStatsDto + { + public int TotalCategories { get; set; } + public int TotalTopics { get; set; } + public int TotalPosts { get; set; } + public int TotalUsers { get; set; } + public int OnlineUsers { get; set; } + public ForumTopicListDto LatestTopic { get; set; } + public List PopularTags { get; set; } + + public ForumStatsDto() + { + PopularTags = new List(); + } + } +} diff --git a/api/src/Kurs.Platform.Application.Contracts/Forum/IForumAppService.cs b/api/src/Kurs.Platform.Application.Contracts/Forum/IForumAppService.cs new file mode 100644 index 00000000..0882cd92 --- /dev/null +++ b/api/src/Kurs.Platform.Application.Contracts/Forum/IForumAppService.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace Kurs.Platform.Forum +{ + public interface IForumAppService : IApplicationService + { + // Category methods + Task> GetCategoriesAsync(); + Task GetCategoryAsync(Guid id); + Task GetCategoryBySlugAsync(string slug); + Task> GetPostsByCategoryAsync(Guid categoryId, int page = 1, int pageSize = 20); + Task CreateCategoryAsync(CreateUpdateForumCategoryDto input); + Task UpdateCategoryAsync(Guid id, CreateUpdateForumCategoryDto input); + Task DeleteCategoryAsync(Guid id); + + // Topic methods + Task> GetTopicsAsync(GetForumTopicsInput input); + Task GetTopicAsync(Guid id); + Task CreateTopicAsync(CreateForumTopicDto input); + Task UpdateTopicAsync(Guid id, UpdateForumTopicDto input); + Task DeleteTopicAsync(Guid id); + + // Topic actions + Task PinTopicAsync(Guid id); + Task UnpinTopicAsync(Guid id); + Task LockTopicAsync(Guid id); + Task UnlockTopicAsync(Guid id); + Task MarkAsSolvedAsync(Guid id); + Task MarkAsUnsolvedAsync(Guid id); + Task LikeTopicAsync(Guid id); + Task UnlikeTopicAsync(Guid id); + Task IncrementViewCountAsync(Guid id); + + // Search and filters + Task> SearchTopicsAsync(SearchForumTopicsInput input); + Task> GetMyTopicsAsync(PagedAndSortedResultRequestDto input); + Task> GetTopicsByTagAsync(string tag, PagedAndSortedResultRequestDto input); + + // Stats + Task GetStatsAsync(); + Task> GetPopularTagsAsync(int count = 20); + } + + public class GetForumTopicsInput : PagedAndSortedResultRequestDto + { + public Guid? CategoryId { get; set; } + public string Filter { get; set; } + public bool? IsPinned { get; set; } + public bool? IsLocked { get; set; } + public bool? IsSolved { get; set; } + public string SortBy { get; set; } = "latest"; // latest, popular, mostviewed + } + + public class SearchForumTopicsInput : PagedAndSortedResultRequestDto + { + public string Query { get; set; } + public Guid? CategoryId { get; set; } + public string Tag { get; set; } + public Guid? AuthorId { get; set; } + public bool? IsSolved { get; set; } + } +} diff --git a/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs b/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs new file mode 100644 index 00000000..517b0cb0 --- /dev/null +++ b/api/src/Kurs.Platform.Application/Blog/BlogAppService.cs @@ -0,0 +1,600 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; + +namespace Kurs.Platform.Blog +{ + [Authorize] + public class BlogAppService : ApplicationService, IBlogAppService + { + private readonly IRepository _postRepository; + private readonly IRepository _categoryRepository; + private readonly IRepository _tagRepository; + private readonly IRepository _postLikeRepository; + private readonly ICurrentUser _currentUser; + + public BlogAppService( + IRepository postRepository, + IRepository categoryRepository, + IRepository tagRepository, + IRepository postLikeRepository, + ICurrentUser currentUser) + { + _postRepository = postRepository; + _categoryRepository = categoryRepository; + _tagRepository = tagRepository; + _postLikeRepository = postLikeRepository; + _currentUser = currentUser; + } + + // Blog Post methods + public async Task> GetPostsAsync(GetBlogPostsInput input) + { + var query = await _postRepository.GetQueryableAsync(); + + if (!string.IsNullOrWhiteSpace(input.Filter)) + { + query = query.Where(x => x.Title.Contains(input.Filter) || x.Summary.Contains(input.Filter)); + } + + if (input.CategoryId.HasValue) + { + query = query.Where(x => x.CategoryId == input.CategoryId.Value); + } + + if (!string.IsNullOrWhiteSpace(input.Tag)) + { + var postIds = await _tagRepository + .GetListAsync(x => x.Tag == input.Tag) + .ContinueWith(t => t.Result.Select(x => x.PostId).ToList()); + + query = query.Where(x => postIds.Contains(x.Id)); + } + + if (input.AuthorId.HasValue) + { + query = query.Where(x => x.AuthorId == input.AuthorId.Value); + } + + if (input.IsPublished.HasValue) + { + query = query.Where(x => x.IsPublished == input.IsPublished.Value); + } + + // Sorting + if (input.SortBy == "popular") + { + query = query.OrderByDescending(x => x.LikeCount); + } + else if (input.SortBy == "trending") + { + query = query.OrderByDescending(x => x.ViewCount); + } + else // latest + { + query = query.OrderByDescending(x => x.CreationTime); + } + + var totalCount = await AsyncExecuter.CountAsync(query); + var posts = await AsyncExecuter.ToListAsync( + query.Skip(input.SkipCount).Take(input.MaxResultCount) + ); + + var postDtos = new List(); + foreach (var post in posts) + { + var dto = ObjectMapper.Map(post); + + // Get category + var category = await _categoryRepository.GetAsync(post.CategoryId); + dto.Category = ObjectMapper.Map(category); + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.PostId == post.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + // Get author info + dto.Author = new AuthorDto + { + Id = post.AuthorId, + Name = post.CreatorId.HasValue ? "User" : "Unknown" // You should get actual user name + }; + + postDtos.Add(dto); + } + + return new PagedResultDto(totalCount, postDtos); + } + + public async Task GetPostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + var dto = ObjectMapper.Map(post); + + // Get category + dto.Category = ObjectMapper.Map( + await _categoryRepository.GetAsync(post.CategoryId) + ); + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.PostId == post.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + // Get author info + dto.Author = new AuthorDto + { + Id = post.AuthorId, + Name = post.CreatorId.HasValue ? "User" : "Unknown" + }; + + // Check if current user liked this post + if (_currentUser.IsAuthenticated) + { + dto.IsLiked = await _postLikeRepository.AnyAsync( + x => x.PostId == id && x.UserId == _currentUser.Id.Value + ); + } + + return dto; + } + + public async Task GetPostBySlugAsync(string slug) + { + var post = await _postRepository.FirstOrDefaultAsync(x => x.Slug == slug); + if (post == null) + { + throw new EntityNotFoundException(typeof(BlogPost)); + } + + return await GetPostAsync(post.Id); + } + + public async Task CreatePostAsync(CreateUpdateBlogPostDto input) + { + var post = new BlogPost( + GuidGenerator.Create(), + input.Title, + input.Slug, + input.Content, + input.Summary, + input.CategoryId, + _currentUser.Id.Value, + CurrentTenant.Id + ); + + post.CoverImage = input.CoverImage; + + if (input.IsPublished) + { + post.Publish(); + } + + await _postRepository.InsertAsync(post); + + // Add tags + foreach (var tag in input.Tags) + { + await _tagRepository.InsertAsync(new BlogPostTag( + GuidGenerator.Create(), + post.Id, + tag, + CurrentTenant.Id + )); + } + + // Update category post count + var category = await _categoryRepository.GetAsync(input.CategoryId); + category.IncrementPostCount(); + await _categoryRepository.UpdateAsync(category); + + return await GetPostAsync(post.Id); + } + + public async Task UpdatePostAsync(Guid id, CreateUpdateBlogPostDto input) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("Blog.Posts.Update")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + post.Title = input.Title; + post.Slug = input.Slug; + post.Content = input.Content; + post.Summary = input.Summary; + post.CoverImage = input.CoverImage; + + // Update category if changed + if (post.CategoryId != input.CategoryId) + { + var oldCategory = await _categoryRepository.GetAsync(post.CategoryId); + oldCategory.DecrementPostCount(); + await _categoryRepository.UpdateAsync(oldCategory); + + var newCategory = await _categoryRepository.GetAsync(input.CategoryId); + newCategory.IncrementPostCount(); + await _categoryRepository.UpdateAsync(newCategory); + + post.CategoryId = input.CategoryId; + } + + await _postRepository.UpdateAsync(post); + + // Update tags + await _tagRepository.DeleteAsync(x => x.PostId == id); + foreach (var tag in input.Tags) + { + await _tagRepository.InsertAsync(new BlogPostTag( + GuidGenerator.Create(), + post.Id, + tag, + CurrentTenant.Id + )); + } + + return await GetPostAsync(post.Id); + } + + public async Task DeletePostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("Blog.Posts.Delete")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + // Update category post count + var category = await _categoryRepository.GetAsync(post.CategoryId); + category.DecrementPostCount(); + await _categoryRepository.UpdateAsync(category); + + await _postRepository.DeleteAsync(id); + } + + public async Task PublishPostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("Blog.Posts.Publish")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + post.Publish(); + await _postRepository.UpdateAsync(post); + + return await GetPostAsync(id); + } + + public async Task UnpublishPostAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + + // Check if user is author or has permission + if (post.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("Blog.Posts.Publish")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + post.Unpublish(); + await _postRepository.UpdateAsync(post); + + return await GetPostAsync(id); + } + + public async Task LikePostAsync(Guid id) + { + var existingLike = await _postLikeRepository.FirstOrDefaultAsync( + x => x.PostId == id && x.UserId == _currentUser.Id.Value + ); + + if (existingLike == null) + { + await _postLikeRepository.InsertAsync(new BlogPostLike( + GuidGenerator.Create(), + id, + _currentUser.Id.Value, + CurrentTenant.Id + )); + + // Update like count + var post = await _postRepository.GetAsync(id); + var likeCount = await _postLikeRepository.CountAsync(x => x.PostId == id); + post.UpdateLikeCount((int)likeCount); + await _postRepository.UpdateAsync(post); + } + } + + public async Task UnlikePostAsync(Guid id) + { + var existingLike = await _postLikeRepository.FirstOrDefaultAsync( + x => x.PostId == id && x.UserId == _currentUser.Id.Value + ); + + if (existingLike != null) + { + await _postLikeRepository.DeleteAsync(existingLike); + + // Update like count + var post = await _postRepository.GetAsync(id); + var likeCount = await _postLikeRepository.CountAsync(x => x.PostId == id); + post.UpdateLikeCount((int)likeCount); + await _postRepository.UpdateAsync(post); + } + } + + [AllowAnonymous] + public async Task IncrementViewCountAsync(Guid id) + { + var post = await _postRepository.GetAsync(id); + post.IncrementViewCount(); + await _postRepository.UpdateAsync(post); + } + + // Blog Category methods + [AllowAnonymous] + public async Task> GetCategoriesAsync() + { + var categories = await _categoryRepository.GetListAsync(x => x.IsActive); + return ObjectMapper.Map, List>(categories); + } + + public async Task GetCategoryAsync(Guid id) + { + var category = await _categoryRepository.GetAsync(id); + return ObjectMapper.Map(category); + } + + [Authorize("Blog.Categories.Create")] + public async Task CreateCategoryAsync(CreateUpdateBlogCategoryDto input) + { + var category = new BlogCategory( + GuidGenerator.Create(), + input.Name, + input.Slug, + input.Description, + CurrentTenant.Id + ); + + category.Icon = input.Icon; + category.DisplayOrder = input.DisplayOrder; + category.IsActive = input.IsActive; + + await _categoryRepository.InsertAsync(category); + + return ObjectMapper.Map(category); + } + + [Authorize("Blog.Categories.Update")] + public async Task UpdateCategoryAsync(Guid id, CreateUpdateBlogCategoryDto input) + { + var category = await _categoryRepository.GetAsync(id); + + category.Name = input.Name; + category.Slug = input.Slug; + category.Description = input.Description; + category.Icon = input.Icon; + category.DisplayOrder = input.DisplayOrder; + category.IsActive = input.IsActive; + + await _categoryRepository.UpdateAsync(category); + + return ObjectMapper.Map(category); + } + + [Authorize("Blog.Categories.Delete")] + public async Task DeleteCategoryAsync(Guid id) + { + // Check if category has posts + var hasPost = await _postRepository.AnyAsync(x => x.CategoryId == id); + if (hasPost) + { + throw new Volo.Abp.BusinessException("Cannot delete category with posts"); + } + + await _categoryRepository.DeleteAsync(id); + } + + // Search and filters + public async Task> SearchPostsAsync(SearchBlogPostsInput input) + { + var query = await _postRepository.GetQueryableAsync(); + + if (!string.IsNullOrWhiteSpace(input.Query)) + { + query = query.Where(x => + x.Title.Contains(input.Query) || + x.Content.Contains(input.Query) || + x.Summary.Contains(input.Query) + ); + } + + if (input.CategoryId.HasValue) + { + query = query.Where(x => x.CategoryId == input.CategoryId.Value); + } + + if (input.AuthorId.HasValue) + { + query = query.Where(x => x.AuthorId == input.AuthorId.Value); + } + + if (input.IsPublished.HasValue) + { + query = query.Where(x => x.IsPublished == input.IsPublished.Value); + } + + // Search by tag + if (!string.IsNullOrWhiteSpace(input.Tag)) + { + var postIds = await _tagRepository + .GetListAsync(x => x.Tag == input.Tag) + .ContinueWith(t => t.Result.Select(x => x.PostId).ToList()); + + query = query.Where(x => postIds.Contains(x.Id)); + } + + var totalCount = await AsyncExecuter.CountAsync(query); + var posts = await AsyncExecuter.ToListAsync( + query.OrderByDescending(x => x.CreationTime) + .Skip(input.SkipCount) + .Take(input.MaxResultCount) + ); + + var postDtos = new List(); + foreach (var post in posts) + { + var dto = ObjectMapper.Map(post); + + // Get category + var category = await _categoryRepository.GetAsync(post.CategoryId); + dto.Category = ObjectMapper.Map(category); + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.PostId == post.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + // Get author info + dto.Author = new AuthorDto + { + Id = post.AuthorId, + Name = post.CreatorId.HasValue ? "User" : "Unknown" + }; + + postDtos.Add(dto); + } + + return new PagedResultDto(totalCount, postDtos); + } + + public async Task> GetPostsByCategoryAsync(Guid categoryId, PagedAndSortedResultRequestDto input) + { + var searchInput = new GetBlogPostsInput + { + CategoryId = categoryId, + MaxResultCount = input.MaxResultCount, + SkipCount = input.SkipCount, + Sorting = input.Sorting + }; + + return await GetPostsAsync(searchInput); + } + + public async Task> GetPostsByTagAsync(string tag, PagedAndSortedResultRequestDto input) + { + var searchInput = new GetBlogPostsInput + { + Tag = tag, + MaxResultCount = input.MaxResultCount, + SkipCount = input.SkipCount, + Sorting = input.Sorting + }; + + return await GetPostsAsync(searchInput); + } + + public async Task> GetPostsByAuthorAsync(Guid authorId, PagedAndSortedResultRequestDto input) + { + var searchInput = new GetBlogPostsInput + { + AuthorId = authorId, + MaxResultCount = input.MaxResultCount, + SkipCount = input.SkipCount, + Sorting = input.Sorting + }; + + return await GetPostsAsync(searchInput); + } + + // Tags + [AllowAnonymous] + public async Task> GetPopularTagsAsync(int count = 20) + { + var tags = await _tagRepository.GetListAsync(); + + return tags + .GroupBy(x => x.Tag) + .OrderByDescending(g => g.Count()) + .Take(count) + .Select(g => g.Key) + .ToList(); + } + + // Stats + [AllowAnonymous] + public async Task GetStatsAsync() + { + var stats = new BlogStatsDto + { + TotalPosts = (int)await _postRepository.CountAsync(), + PublishedPosts = (int)await _postRepository.CountAsync(x => x.IsPublished), + DraftPosts = (int)await _postRepository.CountAsync(x => !x.IsPublished), + TotalCategories = (int)await _categoryRepository.CountAsync(x => x.IsActive), + TotalViews = (await _postRepository.GetListAsync()).Sum(x => x.ViewCount), + TotalLikes = (await _postRepository.GetListAsync()).Sum(x => x.LikeCount), + TotalComments = 0, // You should implement comment count + PopularTags = await GetPopularTagsAsync(10) + }; + + // Get latest post + var latestPost = await _postRepository + .GetQueryableAsync() + .ContinueWith(async t => + { + var query = await t; + return await AsyncExecuter.FirstOrDefaultAsync( + query.Where(x => x.IsPublished).OrderByDescending(x => x.CreationTime) + ); + }) + .Unwrap(); + + if (latestPost != null) + { + var dto = ObjectMapper.Map(latestPost); + + // Get category + var category = await _categoryRepository.GetAsync(latestPost.CategoryId); + dto.Category = ObjectMapper.Map(category); + + stats.LatestPost = dto; + } + + // Get most viewed post + var mostViewedPost = await _postRepository + .GetQueryableAsync() + .ContinueWith(async t => + { + var query = await t; + return await AsyncExecuter.FirstOrDefaultAsync( + query.Where(x => x.IsPublished).OrderByDescending(x => x.ViewCount) + ); + }) + .Unwrap(); + + if (mostViewedPost != null) + { + var dto = ObjectMapper.Map(mostViewedPost); + + // Get category + var category = await _categoryRepository.GetAsync(mostViewedPost.CategoryId); + dto.Category = ObjectMapper.Map(category); + + stats.MostViewedPost = dto; + } + + return stats; + } + } +} diff --git a/api/src/Kurs.Platform.Application/Forum/ForumAppService.cs b/api/src/Kurs.Platform.Application/Forum/ForumAppService.cs new file mode 100644 index 00000000..96c3df82 --- /dev/null +++ b/api/src/Kurs.Platform.Application/Forum/ForumAppService.cs @@ -0,0 +1,648 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; + +namespace Kurs.Platform.Forum +{ + [Authorize] + public class ForumAppService : PlatformAppService, IForumAppService + { + private readonly IRepository _categoryRepository; + private readonly IRepository _topicRepository; + private readonly IRepository _postRepository; + private readonly IRepository _tagRepository; + private readonly IRepository _topicLikeRepository; + private readonly ICurrentUser _currentUser; + + public ForumAppService( + IRepository categoryRepository, + IRepository topicRepository, + IRepository postRepository, + IRepository tagRepository, + IRepository topicLikeRepository, + ICurrentUser currentUser) + { + _categoryRepository = categoryRepository; + _topicRepository = topicRepository; + _postRepository = postRepository; + _tagRepository = tagRepository; + _topicLikeRepository = topicLikeRepository; + _currentUser = currentUser; + } + + // Category methods + public async Task> GetCategoriesAsync() + { + var categories = await _categoryRepository.GetListAsync(x => x.IsActive); + + return ObjectMapper.Map, List>(categories); + } + + public async Task GetCategoryAsync(Guid id) + { + var category = await _categoryRepository.GetAsync(id); + return ObjectMapper.Map(category); + } + + public async Task GetCategoryBySlugAsync(string slug) + { + var category = await _categoryRepository.FirstOrDefaultAsync(x => x.Slug == slug); + if (category == null) + { + throw new Volo.Abp.Domain.Entities.EntityNotFoundException(typeof(ForumCategory), slug); + } + return ObjectMapper.Map(category); + } + + public async Task> GetPostsByCategoryAsync(Guid categoryId, int page = 1, int pageSize = 20) + { + var topics = await _topicRepository.GetListAsync(x => x.CategoryId == categoryId); + var posts = new List(); + + foreach (var topic in topics.Skip((page - 1) * pageSize).Take(pageSize)) + { + var post = new ForumPostDto + { + Id = topic.Id, + CategoryId = topic.CategoryId, + Title = topic.Title, + Content = topic.Content, + ViewCount = topic.ViewCount, + ReplyCount = topic.ReplyCount, + LikeCount = topic.LikeCount, + CreationTime = topic.CreationTime + }; + + // Get author info + post.Author = new AuthorDto + { + Id = topic.AuthorId, + Name = topic.CreatorId.HasValue ? "User" : "Unknown" + }; + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.TopicId == topic.Id); + post.Tags = tags.Select(x => x.Tag).ToList(); + + // Get last reply + var lastPost = await _postRepository + .GetListAsync(x => x.TopicId == topic.Id) + .ContinueWith(t => t.Result.OrderByDescending(x => x.CreationTime).FirstOrDefault()); + + if (lastPost != null) + { + post.LastReply = new LastReplyDto + { + Id = lastPost.Id, + Author = new AuthorDto + { + Id = lastPost.AuthorId, + Name = "User" + }, + CreationTime = lastPost.CreationTime + }; + } + + posts.Add(post); + } + + return posts; + } + + public async Task CreateCategoryAsync(CreateUpdateForumCategoryDto input) + { + var category = new ForumCategory( + GuidGenerator.Create(), + input.Name, + input.Slug, + input.Description, + input.Icon, + input.DisplayOrder, + CurrentTenant.Id + ); + + category.IsActive = input.IsActive; + category.IsLocked = input.IsLocked; + + await _categoryRepository.InsertAsync(category); + + return ObjectMapper.Map(category); + } + + public async Task UpdateCategoryAsync(Guid id, CreateUpdateForumCategoryDto input) + { + var category = await _categoryRepository.GetAsync(id); + + category.Name = input.Name; + category.Slug = input.Slug; + category.Description = input.Description; + category.Icon = input.Icon; + category.DisplayOrder = input.DisplayOrder; + category.IsActive = input.IsActive; + category.IsLocked = input.IsLocked; + + await _categoryRepository.UpdateAsync(category); + + return ObjectMapper.Map(category); + } + + public async Task DeleteCategoryAsync(Guid id) + { + await _categoryRepository.DeleteAsync(id); + } + + // Topic methods + public async Task> GetTopicsAsync(GetForumTopicsInput input) + { + var query = await _topicRepository.GetQueryableAsync(); + + if (input.CategoryId.HasValue) + { + query = query.Where(x => x.CategoryId == input.CategoryId.Value); + } + + if (!string.IsNullOrWhiteSpace(input.Filter)) + { + query = query.Where(x => x.Title.Contains(input.Filter)); + } + + if (input.IsPinned.HasValue) + { + query = query.Where(x => x.IsPinned == input.IsPinned.Value); + } + + if (input.IsLocked.HasValue) + { + query = query.Where(x => x.IsLocked == input.IsLocked.Value); + } + + if (input.IsSolved.HasValue) + { + query = query.Where(x => x.IsSolved == input.IsSolved.Value); + } + + // Sorting + if (input.SortBy == "popular") + { + query = query.OrderByDescending(x => x.LikeCount); + } + else if (input.SortBy == "mostviewed") + { + query = query.OrderByDescending(x => x.ViewCount); + } + else // latest + { + query = query.OrderByDescending(x => x.CreationTime); + } + + var totalCount = await AsyncExecuter.CountAsync(query); + var topics = await AsyncExecuter.ToListAsync( + query.Skip(input.SkipCount).Take(input.MaxResultCount) + ); + + var topicDtos = new List(); + foreach (var topic in topics) + { + var dto = ObjectMapper.Map(topic); + + // Get category name + var category = await _categoryRepository.GetAsync(topic.CategoryId); + dto.CategoryName = category.Name; + + // Get author info + dto.Author = new AuthorDto + { + Id = topic.AuthorId, + Name = topic.CreatorId.HasValue ? "User" : "Unknown" // You should get actual user name + }; + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.TopicId == topic.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + topicDtos.Add(dto); + } + + return new PagedResultDto(totalCount, topicDtos); + } + + public async Task GetTopicAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + var dto = ObjectMapper.Map(topic); + + // Get category + dto.Category = ObjectMapper.Map( + await _categoryRepository.GetAsync(topic.CategoryId) + ); + + // Get author info + dto.Author = new AuthorDto + { + Id = topic.AuthorId, + Name = topic.CreatorId.HasValue ? "User" : "Unknown" // You should get actual user name + }; + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.TopicId == topic.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + // Check if current user liked this topic + if (_currentUser.IsAuthenticated) + { + dto.IsLiked = await _topicLikeRepository.AnyAsync( + x => x.TopicId == id && x.UserId == _currentUser.Id.Value + ); + } + + return dto; + } + + public async Task CreateTopicAsync(CreateForumTopicDto input) + { + var topic = new ForumTopic( + GuidGenerator.Create(), + input.Title, + input.Content, + input.CategoryId, + _currentUser.Id.Value, + CurrentTenant.Id + ); + + await _topicRepository.InsertAsync(topic); + + // Add tags + foreach (var tag in input.Tags) + { + await _tagRepository.InsertAsync(new ForumTopicTag( + GuidGenerator.Create(), + topic.Id, + tag, + CurrentTenant.Id + )); + } + + // Update category counts + var category = await _categoryRepository.GetAsync(input.CategoryId); + category.IncrementTopicCount(); + await _categoryRepository.UpdateAsync(category); + + return await GetTopicAsync(topic.Id); + } + + public async Task UpdateTopicAsync(Guid id, UpdateForumTopicDto input) + { + var topic = await _topicRepository.GetAsync(id); + + // Check if user is author or has permission + if (topic.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("Forum.Topics.Update")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + topic.Title = input.Title; + topic.Content = input.Content; + + await _topicRepository.UpdateAsync(topic); + + // Update tags + await _tagRepository.DeleteAsync(x => x.TopicId == id); + foreach (var tag in input.Tags) + { + await _tagRepository.InsertAsync(new ForumTopicTag( + GuidGenerator.Create(), + topic.Id, + tag, + CurrentTenant.Id + )); + } + + return await GetTopicAsync(topic.Id); + } + + public async Task DeleteTopicAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + + // Check if user is author or has permission + if (topic.AuthorId != _currentUser.Id && !await AuthorizationService.IsGrantedAsync("Forum.Topics.Delete")) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + // Update category counts + var category = await _categoryRepository.GetAsync(topic.CategoryId); + category.DecrementTopicCount(); + await _categoryRepository.UpdateAsync(category); + + await _topicRepository.DeleteAsync(id); + } + + // Topic actions + public async Task PinTopicAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + topic.Pin(); + await _topicRepository.UpdateAsync(topic); + return await GetTopicAsync(id); + } + + public async Task UnpinTopicAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + topic.Unpin(); + await _topicRepository.UpdateAsync(topic); + return await GetTopicAsync(id); + } + + public async Task LockTopicAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + topic.Lock(); + await _topicRepository.UpdateAsync(topic); + return await GetTopicAsync(id); + } + + public async Task UnlockTopicAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + topic.Unlock(); + await _topicRepository.UpdateAsync(topic); + return await GetTopicAsync(id); + } + + public async Task MarkAsSolvedAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + + // Only author can mark as solved + if (topic.AuthorId != _currentUser.Id) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + topic.MarkAsSolved(); + await _topicRepository.UpdateAsync(topic); + return await GetTopicAsync(id); + } + + public async Task MarkAsUnsolvedAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + + // Only author can mark as unsolved + if (topic.AuthorId != _currentUser.Id) + { + throw new Volo.Abp.Authorization.AbpAuthorizationException(); + } + + topic.MarkAsUnsolved(); + await _topicRepository.UpdateAsync(topic); + return await GetTopicAsync(id); + } + + public async Task LikeTopicAsync(Guid id) + { + var existingLike = await _topicLikeRepository.FirstOrDefaultAsync( + x => x.TopicId == id && x.UserId == _currentUser.Id.Value + ); + + if (existingLike == null) + { + await _topicLikeRepository.InsertAsync(new ForumTopicLike( + GuidGenerator.Create(), + id, + _currentUser.Id.Value, + CurrentTenant.Id + )); + + // Update like count + var topic = await _topicRepository.GetAsync(id); + var likeCount = await _topicLikeRepository.CountAsync(x => x.TopicId == id); + topic.UpdateLikeCount((int)likeCount); + await _topicRepository.UpdateAsync(topic); + } + } + + public async Task UnlikeTopicAsync(Guid id) + { + var existingLike = await _topicLikeRepository.FirstOrDefaultAsync( + x => x.TopicId == id && x.UserId == _currentUser.Id.Value + ); + + if (existingLike != null) + { + await _topicLikeRepository.DeleteAsync(existingLike); + + // Update like count + var topic = await _topicRepository.GetAsync(id); + var likeCount = await _topicLikeRepository.CountAsync(x => x.TopicId == id); + topic.UpdateLikeCount((int)likeCount); + await _topicRepository.UpdateAsync(topic); + } + } + + [AllowAnonymous] + public async Task IncrementViewCountAsync(Guid id) + { + var topic = await _topicRepository.GetAsync(id); + topic.IncrementViewCount(); + await _topicRepository.UpdateAsync(topic); + } + + // Search and filters + public async Task> SearchTopicsAsync(SearchForumTopicsInput input) + { + var query = await _topicRepository.GetQueryableAsync(); + + if (!string.IsNullOrWhiteSpace(input.Query)) + { + query = query.Where(x => + x.Title.Contains(input.Query) || + x.Content.Contains(input.Query) + ); + } + + if (input.CategoryId.HasValue) + { + query = query.Where(x => x.CategoryId == input.CategoryId.Value); + } + + if (input.AuthorId.HasValue) + { + query = query.Where(x => x.AuthorId == input.AuthorId.Value); + } + + if (input.IsSolved.HasValue) + { + query = query.Where(x => x.IsSolved == input.IsSolved.Value); + } + + // Search by tag + if (!string.IsNullOrWhiteSpace(input.Tag)) + { + var topicIds = await _tagRepository + .GetListAsync(x => x.Tag == input.Tag) + .ContinueWith(t => t.Result.Select(x => x.TopicId).ToList()); + + query = query.Where(x => topicIds.Contains(x.Id)); + } + + var totalCount = await AsyncExecuter.CountAsync(query); + var topics = await AsyncExecuter.ToListAsync( + query.OrderByDescending(x => x.CreationTime) + .Skip(input.SkipCount) + .Take(input.MaxResultCount) + ); + + var topicDtos = new List(); + foreach (var topic in topics) + { + var dto = ObjectMapper.Map(topic); + + // Get category name + var category = await _categoryRepository.GetAsync(topic.CategoryId); + dto.CategoryName = category.Name; + + // Get author info + dto.Author = new AuthorDto + { + Id = topic.AuthorId, + Name = topic.CreatorId.HasValue ? "User" : "Unknown" + }; + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.TopicId == topic.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + topicDtos.Add(dto); + } + + return new PagedResultDto(totalCount, topicDtos); + } + + public async Task> GetMyTopicsAsync(PagedAndSortedResultRequestDto input) + { + var searchInput = new GetForumTopicsInput + { + MaxResultCount = input.MaxResultCount, + SkipCount = input.SkipCount, + Sorting = input.Sorting + }; + + var query = await _topicRepository.GetQueryableAsync(); + query = query.Where(x => x.AuthorId == _currentUser.Id.Value); + + var totalCount = await AsyncExecuter.CountAsync(query); + var topics = await AsyncExecuter.ToListAsync( + query.OrderByDescending(x => x.CreationTime) + .Skip(input.SkipCount) + .Take(input.MaxResultCount) + ); + + var topicDtos = new List(); + foreach (var topic in topics) + { + var dto = ObjectMapper.Map(topic); + + // Get category name + var category = await _categoryRepository.GetAsync(topic.CategoryId); + dto.CategoryName = category.Name; + + // Get author info + dto.Author = new AuthorDto + { + Id = topic.AuthorId, + Name = _currentUser.Name ?? _currentUser.UserName + }; + + // Get tags + var tags = await _tagRepository.GetListAsync(x => x.TopicId == topic.Id); + dto.Tags = tags.Select(x => x.Tag).ToList(); + + topicDtos.Add(dto); + } + + return new PagedResultDto(totalCount, topicDtos); + } + + public async Task> GetTopicsByTagAsync(string tag, PagedAndSortedResultRequestDto input) + { + var searchInput = new SearchForumTopicsInput + { + Tag = tag, + MaxResultCount = input.MaxResultCount, + SkipCount = input.SkipCount, + Sorting = input.Sorting + }; + + return await SearchTopicsAsync(searchInput); + } + + // Stats + [AllowAnonymous] + public async Task GetStatsAsync() + { + var stats = new ForumStatsDto + { + TotalCategories = (int)await _categoryRepository.CountAsync(x => x.IsActive), + TotalTopics = (int)await _topicRepository.CountAsync(), + TotalPosts = (int)await _postRepository.CountAsync(), + TotalUsers = 100, // You should get this from identity service + OnlineUsers = 10, // You should implement online user tracking + PopularTags = await GetPopularTagsAsync(10) + }; + + // Get latest topic + var latestTopic = await _topicRepository + .GetQueryableAsync() + .ContinueWith(async t => + { + var query = await t; + return await AsyncExecuter.FirstOrDefaultAsync( + query.OrderByDescending(x => x.CreationTime) + ); + }) + .Unwrap(); + + if (latestTopic != null) + { + var dto = ObjectMapper.Map(latestTopic); + + // Get category name + var category = await _categoryRepository.GetAsync(latestTopic.CategoryId); + dto.CategoryName = category.Name; + + // Get author info + dto.Author = new AuthorDto + { + Id = latestTopic.AuthorId, + Name = "User" + }; + + stats.LatestTopic = dto; + } + + return stats; + } + + [AllowAnonymous] + public async Task> GetPopularTagsAsync(int count = 20) + { + var tags = await _tagRepository.GetListAsync(); + + return tags + .GroupBy(x => x.Tag) + .OrderByDescending(g => g.Count()) + .Take(count) + .Select(g => g.Key) + .ToList(); + } + } +} diff --git a/api/src/Kurs.Platform.Application/Identity/PlatformIdentityAppService.cs b/api/src/Kurs.Platform.Application/Identity/PlatformIdentityAppService.cs index f6d92b98..43712ebe 100644 --- a/api/src/Kurs.Platform.Application/Identity/PlatformIdentityAppService.cs +++ b/api/src/Kurs.Platform.Application/Identity/PlatformIdentityAppService.cs @@ -7,7 +7,6 @@ using Kurs.Platform.Entities; using Kurs.Platform.Extensions; using Kurs.Platform.Identity.Dto; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; using Volo.Abp.Guids; diff --git a/api/src/Kurs.Platform.Application/PlatformApplicationAutoMapperProfile.cs b/api/src/Kurs.Platform.Application/PlatformApplicationAutoMapperProfile.cs index b49a59cb..e6b73c00 100644 --- a/api/src/Kurs.Platform.Application/PlatformApplicationAutoMapperProfile.cs +++ b/api/src/Kurs.Platform.Application/PlatformApplicationAutoMapperProfile.cs @@ -1,13 +1,6 @@ using AutoMapper; -using Kurs.Platform.Contacts; -using Kurs.Platform.Currencies; -using Kurs.Platform.Entities; -using Kurs.Platform.GlobalSearchs; -using Kurs.Platform.OrganizationUnits; -using Kurs.Platform.Sectors; -using Kurs.Platform.Skills; -using Kurs.Platform.Uoms; -using Volo.Abp.Identity; +using Kurs.Platform.Blog; +using Kurs.Platform.Forum; namespace Kurs.Platform; @@ -15,28 +8,19 @@ public class PlatformApplicationAutoMapperProfile : Profile { public PlatformApplicationAutoMapperProfile() { - CreateMap(); - CreateMap(); - CreateMap(); + /* You can configure your AutoMapper mapping configuration here. + * Alternatively, you can split your mapping configurations + * into multiple profile classes for a better organization. */ - CreateMap(); - - CreateMap(); - CreateMap(); - CreateMap() - .ForMember(dest => dest.UomCategoryName, opt => opt.MapFrom(src => src.UomCategory.Name)); - CreateMap(); - CreateMap(); - CreateMap() - .ForMember(dest => dest.BankName, opt => opt.MapFrom(src => src.Bank.Name)) - .ForMember(dest => dest.CurrencyCode, opt => opt.MapFrom(src => src.Currency.Code)); - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); + // Blog mappings + CreateMap(); + CreateMap(); + CreateMap(); + + // Forum mappings + CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.CreatedAt, opt => opt.MapFrom(src => src.CreationTime)); } } diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index d6375fb4..b3262ae1 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -522,6 +522,18 @@ "en": "Abp Settings", "tr": "Abp Ayarları" }, + { + "resourceName": "Platform", + "key": "App.Blog", + "en": "Blog", + "tr": "Blog" + }, + { + "resourceName": "Platform", + "key": "App.Forum", + "en": "Forum", + "tr": "Forum" + }, { "resourceName": "Platform", "key": "App.Home", @@ -651,8 +663,8 @@ { "resourceName": "Platform", "key": "AbpTenantManagement", - "en": "Tenants", - "tr": "Tenants" + "en": "Organizations", + "tr": "Kurumlar" }, { "resourceName": "Platform", @@ -663,8 +675,8 @@ { "resourceName": "Platform", "key": "AbpTenantManagement.Tenants", - "en": "Tenants", - "tr": "Şirketler" + "en": "Organizations", + "tr": "Kurumlar" }, { "resourceName": "Platform", @@ -2409,8 +2421,8 @@ { "resourceName": "Platform", "key": "Sirket", - "en": "Tenant", - "tr": "Şirket" + "en": "Organization", + "tr": "Kurum" }, { "resourceName": "Platform", @@ -5878,96 +5890,6 @@ "RequiredPermissionName": "App.Setting", "IsDisabled": false }, - { - "ParentCode": "App.Administration", - "Code": "Abp.Identity", - "DisplayName": "Abp.Identity", - "Order": 2, - "Url": null, - "Icon": "FcConferenceCall", - "RequiredPermissionName": null, - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "Abp.Identity.PermissionGroups", - "DisplayName": "Abp.Identity.PermissionGroups", - "Order": 1, - "Url": "/list/list-permissiongroup", - "Icon": "FcEngineering", - "RequiredPermissionName": "Abp.Identity.PermissionGroups", - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "Abp.Identity.Permissions", - "DisplayName": "Abp.Identity.Permissions", - "Order": 2, - "Url": "/list/list-permission", - "Icon": "FcSupport", - "RequiredPermissionName": "Abp.Identity.Permissions", - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "AbpIdentity.Roles", - "DisplayName": "AbpIdentity.Roles", - "Order": 3, - "Url": "/list/list-role", - "Icon": "FcFlowChart", - "RequiredPermissionName": "AbpIdentity.Roles", - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "AbpIdentity.Users", - "DisplayName": "AbpIdentity.Users", - "Order": 4, - "Url": "/list/list-user", - "Icon": "FcBusinessman", - "RequiredPermissionName": "AbpIdentity.Users", - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "Abp.Identity.OrganizationUnits", - "DisplayName": "Abp.Identity.OrganizationUnits", - "Order": 5, - "Url": "/admin/ous", - "Icon": "FcOrganization", - "RequiredPermissionName": "Abp.Identity.OrganizationUnits", - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "AbpIdentity.Users.ClaimType", - "DisplayName": "AbpIdentity.Users.ClaimType", - "Order": 6, - "Url": "/list/list-claimtype", - "Icon": "FcOrganization", - "RequiredPermissionName": "AbpIdentity.Users.ClaimType", - "IsDisabled": false - }, - { - "ParentCode": "Abp.Identity", - "Code": "App.IpRestrictions", - "DisplayName": "App.IpRestrictions", - "Order": 7, - "Url": "/list/list-iprestriction", - "Icon": "FcNfcSign", - "RequiredPermissionName": "App.IpRestrictions", - "IsDisabled": false - }, - { - "ParentCode": "AbpIdentity.Users", - "Code": "AbpIdentity.Users.SecurityLog", - "DisplayName": "AbpIdentity.Users.SecurityLog", - "Order": 8, - "Url": "/list/list-securitylog", - "Icon": "FcPrivacy", - "RequiredPermissionName": "AbpIdentity.Users.SecurityLog", - "IsDisabled": false - }, { "ParentCode": "App.Saas", "Code": "App.Listforms", @@ -6068,6 +5990,116 @@ "RequiredPermissionName": "App.PublicApis", "IsDisabled": false }, + { + "ParentCode": "App.Saas", + "Code": "App.Blog", + "DisplayName": "App.Blog", + "Order": 10, + "Url": "/admin/blog/management", + "Icon": "FcTemplate", + "RequiredPermissionName": "App.Blog", + "IsDisabled": false + }, + { + "ParentCode": "App.Saas", + "Code": "App.Forum", + "DisplayName": "App.Forum", + "Order": 11, + "Url": "/admin/forum/management", + "Icon": "FcReading", + "RequiredPermissionName": "App.Forum", + "IsDisabled": false + }, + { + "ParentCode": "App.Administration", + "Code": "Abp.Identity", + "DisplayName": "Abp.Identity", + "Order": 2, + "Url": null, + "Icon": "FcConferenceCall", + "RequiredPermissionName": null, + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "Abp.Identity.PermissionGroups", + "DisplayName": "Abp.Identity.PermissionGroups", + "Order": 1, + "Url": "/list/list-permissiongroup", + "Icon": "FcEngineering", + "RequiredPermissionName": "Abp.Identity.PermissionGroups", + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "Abp.Identity.Permissions", + "DisplayName": "Abp.Identity.Permissions", + "Order": 2, + "Url": "/list/list-permission", + "Icon": "FcSupport", + "RequiredPermissionName": "Abp.Identity.Permissions", + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "AbpIdentity.Roles", + "DisplayName": "AbpIdentity.Roles", + "Order": 3, + "Url": "/list/list-role", + "Icon": "FcFlowChart", + "RequiredPermissionName": "AbpIdentity.Roles", + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "AbpIdentity.Users", + "DisplayName": "AbpIdentity.Users", + "Order": 4, + "Url": "/list/list-user", + "Icon": "FcBusinessman", + "RequiredPermissionName": "AbpIdentity.Users", + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "Abp.Identity.OrganizationUnits", + "DisplayName": "Abp.Identity.OrganizationUnits", + "Order": 5, + "Url": "/admin/ous", + "Icon": "FcOrganization", + "RequiredPermissionName": "Abp.Identity.OrganizationUnits", + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "AbpIdentity.Users.ClaimType", + "DisplayName": "AbpIdentity.Users.ClaimType", + "Order": 6, + "Url": "/list/list-claimtype", + "Icon": "FcOrganization", + "RequiredPermissionName": "AbpIdentity.Users.ClaimType", + "IsDisabled": false + }, + { + "ParentCode": "Abp.Identity", + "Code": "App.IpRestrictions", + "DisplayName": "App.IpRestrictions", + "Order": 7, + "Url": "/list/list-iprestriction", + "Icon": "FcNfcSign", + "RequiredPermissionName": "App.IpRestrictions", + "IsDisabled": false + }, + { + "ParentCode": "AbpIdentity.Users", + "Code": "AbpIdentity.Users.SecurityLog", + "DisplayName": "AbpIdentity.Users.SecurityLog", + "Order": 8, + "Url": "/list/list-securitylog", + "Icon": "FcPrivacy", + "RequiredPermissionName": "AbpIdentity.Users.SecurityLog", + "IsDisabled": false + }, { "ParentCode": "App.Administration", "Code": "App.AuditLogs", @@ -6135,7 +6167,15 @@ { "Name": "App.AuditLogs", "DisplayName": "App.AuditLogs" - } + }, + { + "Name": "App.Blog", + "DisplayName": "App.Blog" + }, + { + "Name": "App.Forum", + "DisplayName": "App.Forum" + } ], "PermissionDefinitionRecords": [ { @@ -6330,6 +6370,22 @@ "IsEnabled": true, "MultiTenancySide": 2 }, + { + "GroupName": "App.Blog", + "Name": "App.Blog", + "ParentName": null, + "DisplayName": "App.Blog", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Forum", + "Name": "App.Forum", + "ParentName": null, + "DisplayName": "App.Forum", + "IsEnabled": true, + "MultiTenancySide": 2 + }, { "GroupName": "App.Setting", "Name": "Abp.Account", @@ -7329,6 +7385,70 @@ "DisplayName": "App.SiteManagement.Theme", "IsEnabled": true, "MultiTenancySide": 3 + }, + { + "GroupName": "App.Blog", + "Name": "App.Blog.Create", + "ParentName": "App.Blog", + "DisplayName": "Create", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Blog", + "Name": "App.Blog.Delete", + "ParentName": "App.Blog", + "DisplayName": "Delete", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Blog", + "Name": "App.Blog.Export", + "ParentName": "App.Blog", + "DisplayName": "Export", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Blog", + "Name": "App.Blog.Update", + "ParentName": "App.Blog", + "DisplayName": "Update", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Forum", + "Name": "App.Forum.Create", + "ParentName": "App.Forum", + "DisplayName": "Create", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Forum", + "Name": "App.Forum.Delete", + "ParentName": "App.Forum", + "DisplayName": "Delete", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Forum", + "Name": "App.Forum.Export", + "ParentName": "App.Forum", + "DisplayName": "Export", + "IsEnabled": true, + "MultiTenancySide": 2 + }, + { + "GroupName": "App.Forum", + "Name": "App.Forum.Update", + "ParentName": "App.Forum", + "DisplayName": "Update", + "IsEnabled": true, + "MultiTenancySide": 2 } ], "Sectors": [ @@ -19531,5 +19651,39 @@ { "Title": "Bayan", "Abbreviation": "Bayan" }, { "Title": "Doktora", "Abbreviation": "Dr." }, { "Title": "Profesör", "Abbreviation": "Prof." } + ], + "ForumCategories": [ + { + "Name": "Genel Tartışma", + "Slug": "genel-tartisma", + "Description": "Her türlü konunun tartışılabileceği genel forum alanı", + "Icon": "💬", + "Order": 1, + "IsActive": true + }, + { + "Name": "Teknik Destek", + "Slug": "teknik-destek", + "Description": "Teknik sorunlar ve çözümler için destek forumu", + "Icon": "🔧", + "Order": 2, + "IsActive": true + }, + { + "Name": "Öneriler", + "Slug": "oneriler", + "Description": "Platform geliştirmeleri için öneri ve istekler", + "Icon": "💡", + "Order": 3, + "IsActive": true + }, + { + "Name": "Duyurular", + "Slug": "duyurular", + "Description": "Platform duyuruları ve güncellemeler", + "Icon": "📢", + "Order": 4, + "IsActive": true + } ] } diff --git a/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs b/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs index fd805301..69077b5e 100644 --- a/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs +++ b/api/src/Kurs.Platform.Domain.Shared/PlatformConsts.cs @@ -302,7 +302,9 @@ public static class PlatformConsts } public const string AuditLogs = Prefix.App + ".AuditLogs"; - public const string EntityChanges = Prefix.App + ".EntityChanges"; + public const string Branches = Prefix.App + ".Branches"; + public const string Forum = Prefix.App + ".Forum"; + public const string Blog = Prefix.App + ".Blog"; } public static class ListFormCodes diff --git a/api/src/Kurs.Platform.Domain/Blog/BlogCategory.cs b/api/src/Kurs.Platform.Domain/Blog/BlogCategory.cs new file mode 100644 index 00000000..7b6bc792 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Blog/BlogCategory.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Blog +{ + public class BlogCategory : FullAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public string Name { get; set; } + public string Slug { get; set; } + public string Description { get; set; } + public string Icon { get; set; } + public int DisplayOrder { get; set; } + public bool IsActive { get; set; } + public int PostCount { get; set; } + + public virtual ICollection Posts { get; set; } + + protected BlogCategory() + { + Posts = new HashSet(); + } + + public BlogCategory( + Guid id, + string name, + string slug, + string description = null, + Guid? tenantId = null) : base(id) + { + Name = name; + Slug = slug; + Description = description; + TenantId = tenantId; + Icon = null; + DisplayOrder = 0; + IsActive = true; + PostCount = 0; + Posts = new HashSet(); + } + + public void IncrementPostCount() + { + PostCount++; + } + + public void DecrementPostCount() + { + if (PostCount > 0) + PostCount--; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Blog/BlogComment.cs b/api/src/Kurs.Platform.Domain/Blog/BlogComment.cs new file mode 100644 index 00000000..64fcf858 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Blog/BlogComment.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Blog +{ + public class BlogComment : FullAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid PostId { get; set; } + public virtual BlogPost Post { get; set; } + + public string Content { get; set; } + + public Guid AuthorId { get; set; } + + public Guid? ParentId { get; set; } + public virtual BlogComment Parent { get; set; } + + public virtual ICollection Replies { get; set; } + public virtual ICollection Likes { get; set; } + + public int LikeCount { get; set; } + + protected BlogComment() + { + Replies = new HashSet(); + Likes = new HashSet(); + } + + public BlogComment( + Guid id, + Guid postId, + string content, + Guid authorId, + Guid? parentId = null, + Guid? tenantId = null) : base(id) + { + PostId = postId; + Content = content; + AuthorId = authorId; + ParentId = parentId; + TenantId = tenantId; + LikeCount = 0; + + Replies = new HashSet(); + Likes = new HashSet(); + } + + public void UpdateLikeCount(int count) + { + LikeCount = count; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Blog/BlogCommentLike.cs b/api/src/Kurs.Platform.Domain/Blog/BlogCommentLike.cs new file mode 100644 index 00000000..19fa09f5 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Blog/BlogCommentLike.cs @@ -0,0 +1,31 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Blog +{ + public class BlogCommentLike : CreationAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid CommentId { get; set; } + public virtual BlogComment Comment { get; set; } + + public Guid UserId { get; set; } + + protected BlogCommentLike() + { + } + + public BlogCommentLike( + Guid id, + Guid commentId, + Guid userId, + Guid? tenantId = null) : base(id) + { + CommentId = commentId; + UserId = userId; + TenantId = tenantId; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Blog/BlogPost.cs b/api/src/Kurs.Platform.Domain/Blog/BlogPost.cs new file mode 100644 index 00000000..09c0a0d8 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Blog/BlogPost.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Blog +{ + public class BlogPost : FullAuditedAggregateRoot, IMultiTenant + { + public Guid? TenantId { get; set; } + + public string Title { get; set; } + public string Slug { get; set; } + public string Content { get; set; } + public string Summary { get; set; } + public string CoverImage { get; set; } + + public Guid CategoryId { get; set; } + public virtual BlogCategory Category { get; set; } + + public Guid AuthorId { get; set; } + + public int ViewCount { get; set; } + public int LikeCount { get; set; } + public int CommentCount { get; set; } + + public bool IsPublished { get; set; } + public DateTime? PublishedAt { get; set; } + + public virtual ICollection Tags { get; set; } + public virtual ICollection Comments { get; set; } + public virtual ICollection Likes { get; set; } + + protected BlogPost() + { + Tags = new HashSet(); + Comments = new HashSet(); + Likes = new HashSet(); + } + + public BlogPost( + Guid id, + string title, + string slug, + string content, + string summary, + Guid categoryId, + Guid authorId, + Guid? tenantId = null) : base(id) + { + Title = title; + Slug = slug; + Content = content; + Summary = summary; + CategoryId = categoryId; + AuthorId = authorId; + TenantId = tenantId; + + ViewCount = 0; + LikeCount = 0; + CommentCount = 0; + IsPublished = false; + + Tags = new HashSet(); + Comments = new HashSet(); + Likes = new HashSet(); + } + + public void Publish() + { + IsPublished = true; + PublishedAt = DateTime.UtcNow; + } + + public void Unpublish() + { + IsPublished = false; + PublishedAt = null; + } + + public void IncrementViewCount() + { + ViewCount++; + } + + public void UpdateLikeCount(int count) + { + LikeCount = count; + } + + public void UpdateCommentCount(int count) + { + CommentCount = count; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Blog/BlogPostLike.cs b/api/src/Kurs.Platform.Domain/Blog/BlogPostLike.cs new file mode 100644 index 00000000..c4e2c1e9 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Blog/BlogPostLike.cs @@ -0,0 +1,31 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Blog +{ + public class BlogPostLike : CreationAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid PostId { get; set; } + public virtual BlogPost Post { get; set; } + + public Guid UserId { get; set; } + + protected BlogPostLike() + { + } + + public BlogPostLike( + Guid id, + Guid postId, + Guid userId, + Guid? tenantId = null) : base(id) + { + PostId = postId; + UserId = userId; + TenantId = tenantId; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Blog/BlogPostTag.cs b/api/src/Kurs.Platform.Domain/Blog/BlogPostTag.cs new file mode 100644 index 00000000..f98242bd --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Blog/BlogPostTag.cs @@ -0,0 +1,31 @@ +using System; +using Volo.Abp.Domain.Entities; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Blog +{ + public class BlogPostTag : Entity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid PostId { get; set; } + public virtual BlogPost Post { get; set; } + + public string Tag { get; set; } + + protected BlogPostTag() + { + } + + public BlogPostTag( + Guid id, + Guid postId, + string tag, + Guid? tenantId = null) : base(id) + { + PostId = postId; + Tag = tag; + TenantId = tenantId; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Data/ForumDataSeedContributor.cs b/api/src/Kurs.Platform.Domain/Data/ForumDataSeedContributor.cs new file mode 100644 index 00000000..9915e85e --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Data/ForumDataSeedContributor.cs @@ -0,0 +1,58 @@ +using System; +using System.Threading.Tasks; +using Kurs.Platform.Forum; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace Kurs.Platform.Data +{ + public class ForumDataSeedContributor : IDataSeedContributor, ITransientDependency + { + private readonly IRepository _categoryRepository; + private readonly IGuidGenerator _guidGenerator; + + public ForumDataSeedContributor( + IRepository categoryRepository, + IGuidGenerator guidGenerator) + { + _categoryRepository = categoryRepository; + _guidGenerator = guidGenerator; + } + + public async Task SeedAsync(DataSeedContext context) + { + if (await _categoryRepository.AnyAsync()) + { + return; + } + + var categories = new[] + { + new { Name = "Genel Tartışma", Slug = "genel-tartisma", Description = "Her türlü konunun tartışılabileceği genel forum", Icon = "message-circle", DisplayOrder = 1 }, + new { Name = "Duyurular", Slug = "duyurular", Description = "Sistem duyuruları ve haberler", Icon = "megaphone", DisplayOrder = 2 }, + new { Name = "Teknik Destek", Slug = "teknik-destek", Description = "Teknik sorunlar ve çözümler", Icon = "wrench", DisplayOrder = 3 }, + new { Name = "Öneriler", Slug = "oneriler", Description = "Sistem için öneri ve istekler", Icon = "lightbulb", DisplayOrder = 4 }, + new { Name = "Eğitim", Slug = "egitim", Description = "Eğitim materyalleri ve kaynaklar", Icon = "book", DisplayOrder = 5 } + }; + + foreach (var cat in categories) + { + await _categoryRepository.InsertAsync( + new ForumCategory( + _guidGenerator.Create(), + cat.Name, + cat.Slug, + cat.Description, + cat.Icon, + cat.DisplayOrder, + context.TenantId + ), + autoSave: true + ); + } + } + + } +} diff --git a/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs b/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs index d23b2cb6..4b5ca545 100644 --- a/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs +++ b/api/src/Kurs.Platform.Domain/Data/SeedConsts.cs @@ -363,6 +363,8 @@ public static class SeedConsts public const string PublicApis = Prefix.App + ".PublicApis"; public const string AuditLogs = Prefix.App + ".AuditLogs"; public const string Branches = Prefix.App + ".Branches"; + public const string Forum = Prefix.App + ".Forum"; + public const string Blog = Prefix.App + ".Blog"; } public static class DataSources diff --git a/api/src/Kurs.Platform.Domain/Forum/ForumCategory.cs b/api/src/Kurs.Platform.Domain/Forum/ForumCategory.cs new file mode 100644 index 00000000..5b5c9677 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Forum/ForumCategory.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Forum +{ + public class ForumCategory : FullAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public string Name { get; set; } + public string Slug { get; set; } + public string Description { get; set; } + public string Icon { get; set; } + public int DisplayOrder { get; set; } + public bool IsActive { get; set; } + public bool IsLocked { get; set; } + + public int TopicCount { get; set; } + public int PostCount { get; set; } + + public Guid? LastPostId { get; set; } + public DateTime? LastPostDate { get; set; } + public Guid? LastPostUserId { get; set; } + + public virtual ICollection Topics { get; set; } + + protected ForumCategory() + { + Topics = new HashSet(); + } + + public ForumCategory( + Guid id, + string name, + string slug, + string description, + string icon = null, + int displayOrder = 0, + Guid? tenantId = null) : base(id) + { + Name = name; + Slug = slug; + Description = description; + Icon = icon; + DisplayOrder = displayOrder; + TenantId = tenantId; + IsActive = true; + IsLocked = false; + TopicCount = 0; + PostCount = 0; + + Topics = new HashSet(); + } + + public void UpdateLastPost(Guid postId, Guid userId) + { + LastPostId = postId; + LastPostDate = DateTime.UtcNow; + LastPostUserId = userId; + } + + public void IncrementTopicCount() + { + TopicCount++; + } + + public void DecrementTopicCount() + { + if (TopicCount > 0) + TopicCount--; + } + + public void IncrementPostCount() + { + PostCount++; + } + + public void DecrementPostCount() + { + if (PostCount > 0) + PostCount--; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Forum/ForumPost.cs b/api/src/Kurs.Platform.Domain/Forum/ForumPost.cs new file mode 100644 index 00000000..f8fa63d8 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Forum/ForumPost.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Forum +{ + public class ForumPost : FullAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid TopicId { get; set; } + public virtual ForumTopic Topic { get; set; } + + public string Content { get; set; } + + public Guid AuthorId { get; set; } + + public int LikeCount { get; set; } + + public bool IsAcceptedAnswer { get; set; } + + public virtual ICollection Likes { get; set; } + + protected ForumPost() + { + Likes = new HashSet(); + } + + public ForumPost( + Guid id, + Guid topicId, + string content, + Guid authorId, + Guid? tenantId = null) : base(id) + { + TopicId = topicId; + Content = content; + AuthorId = authorId; + TenantId = tenantId; + LikeCount = 0; + IsAcceptedAnswer = false; + + Likes = new HashSet(); + } + + public void UpdateLikeCount(int count) + { + LikeCount = count; + } + + public void MarkAsAcceptedAnswer() + { + IsAcceptedAnswer = true; + } + + public void UnmarkAsAcceptedAnswer() + { + IsAcceptedAnswer = false; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Forum/ForumPostLike.cs b/api/src/Kurs.Platform.Domain/Forum/ForumPostLike.cs new file mode 100644 index 00000000..c6494e25 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Forum/ForumPostLike.cs @@ -0,0 +1,31 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Forum +{ + public class ForumPostLike : CreationAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid PostId { get; set; } + public virtual ForumPost Post { get; set; } + + public Guid UserId { get; set; } + + protected ForumPostLike() + { + } + + public ForumPostLike( + Guid id, + Guid postId, + Guid userId, + Guid? tenantId = null) : base(id) + { + PostId = postId; + UserId = userId; + TenantId = tenantId; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Forum/ForumTopic.cs b/api/src/Kurs.Platform.Domain/Forum/ForumTopic.cs new file mode 100644 index 00000000..cc5fef10 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Forum/ForumTopic.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Forum +{ + public class ForumTopic : FullAuditedAggregateRoot, IMultiTenant + { + public Guid? TenantId { get; set; } + + public string Title { get; set; } + public string Content { get; set; } + + public Guid CategoryId { get; set; } + public virtual ForumCategory Category { get; set; } + + public Guid AuthorId { get; set; } + + public int ViewCount { get; set; } + public int ReplyCount { get; set; } + public int LikeCount { get; set; } + + public bool IsPinned { get; set; } + public bool IsLocked { get; set; } + public bool IsSolved { get; set; } + + public Guid? LastPostId { get; set; } + public DateTime? LastPostDate { get; set; } + public Guid? LastPostUserId { get; set; } + + public virtual ICollection Posts { get; set; } + public virtual ICollection Tags { get; set; } + public virtual ICollection Likes { get; set; } + + protected ForumTopic() + { + Posts = new HashSet(); + Tags = new HashSet(); + Likes = new HashSet(); + } + + public ForumTopic( + Guid id, + string title, + string content, + Guid categoryId, + Guid authorId, + Guid? tenantId = null) : base(id) + { + Title = title; + Content = content; + CategoryId = categoryId; + AuthorId = authorId; + TenantId = tenantId; + + ViewCount = 0; + ReplyCount = 0; + LikeCount = 0; + IsPinned = false; + IsLocked = false; + IsSolved = false; + + Posts = new HashSet(); + Tags = new HashSet(); + Likes = new HashSet(); + } + + public void IncrementViewCount() + { + ViewCount++; + } + + public void UpdateLastPost(Guid postId, Guid userId) + { + LastPostId = postId; + LastPostDate = DateTime.UtcNow; + LastPostUserId = userId; + ReplyCount++; + } + + public void UpdateLikeCount(int count) + { + LikeCount = count; + } + + public void Pin() + { + IsPinned = true; + } + + public void Unpin() + { + IsPinned = false; + } + + public void Lock() + { + IsLocked = true; + } + + public void Unlock() + { + IsLocked = false; + } + + public void MarkAsSolved() + { + IsSolved = true; + } + + public void MarkAsUnsolved() + { + IsSolved = false; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Forum/ForumTopicLike.cs b/api/src/Kurs.Platform.Domain/Forum/ForumTopicLike.cs new file mode 100644 index 00000000..4ec46e15 --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Forum/ForumTopicLike.cs @@ -0,0 +1,31 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Forum +{ + public class ForumTopicLike : CreationAuditedEntity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid TopicId { get; set; } + public virtual ForumTopic Topic { get; set; } + + public Guid UserId { get; set; } + + protected ForumTopicLike() + { + } + + public ForumTopicLike( + Guid id, + Guid topicId, + Guid userId, + Guid? tenantId = null) : base(id) + { + TopicId = topicId; + UserId = userId; + TenantId = tenantId; + } + } +} diff --git a/api/src/Kurs.Platform.Domain/Forum/ForumTopicTag.cs b/api/src/Kurs.Platform.Domain/Forum/ForumTopicTag.cs new file mode 100644 index 00000000..6e48beae --- /dev/null +++ b/api/src/Kurs.Platform.Domain/Forum/ForumTopicTag.cs @@ -0,0 +1,31 @@ +using System; +using Volo.Abp.Domain.Entities; +using Volo.Abp.MultiTenancy; + +namespace Kurs.Platform.Forum +{ + public class ForumTopicTag : Entity, IMultiTenant + { + public Guid? TenantId { get; set; } + + public Guid TopicId { get; set; } + public virtual ForumTopic Topic { get; set; } + + public string Tag { get; set; } + + protected ForumTopicTag() + { + } + + public ForumTopicTag( + Guid id, + Guid topicId, + string tag, + Guid? tenantId = null) : base(id) + { + TopicId = topicId; + Tag = tag; + TenantId = tenantId; + } + } +} diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs b/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs index 6f9ec10f..5cb67c5d 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/EntityFrameworkCore/PlatformDbContext.cs @@ -1,5 +1,7 @@ using Kurs.Languages.EntityFrameworkCore; using Kurs.Platform.Entities; +using Kurs.Platform.Blog; +using Kurs.Platform.Forum; using Kurs.Settings.EntityFrameworkCore; using Kurs.MailQueue.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; @@ -57,6 +59,22 @@ public class PlatformDbContext : public DbSet ContactTags { get; set; } public DbSet ContactTitles { get; set; } + // Blog Entities + public DbSet BlogPosts { get; set; } + public DbSet BlogCategories { get; set; } + public DbSet BlogComments { get; set; } + public DbSet BlogPostTags { get; set; } + public DbSet BlogPostLikes { get; set; } + public DbSet BlogCommentLikes { get; set; } + + // Forum Entities + public DbSet ForumCategories { get; set; } + public DbSet ForumTopics { get; set; } + public DbSet ForumPosts { get; set; } + public DbSet ForumTopicTags { get; set; } + public DbSet ForumTopicLikes { get; set; } + public DbSet ForumPostLikes { get; set; } + #region Entities from the modules /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext @@ -391,6 +409,187 @@ public class PlatformDbContext : b.Property(x => x.Abbreviation).HasMaxLength(64); }); + // Blog Entity Configurations + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "BlogCategories", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Name).IsRequired().HasMaxLength(128); + b.Property(x => x.Slug).IsRequired().HasMaxLength(128); + b.Property(x => x.Description).HasMaxLength(512); + + b.HasIndex(x => x.Slug); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "BlogPosts", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Title).IsRequired().HasMaxLength(256); + b.Property(x => x.Slug).IsRequired().HasMaxLength(256); + b.Property(x => x.Summary).IsRequired().HasMaxLength(512); + b.Property(x => x.Content).IsRequired(); + b.Property(x => x.CoverImage).HasMaxLength(512); + + b.HasIndex(x => x.Slug); + b.HasIndex(x => x.IsPublished); + b.HasIndex(x => x.PublishedAt); + + b.HasOne(x => x.Category) + .WithMany(x => x.Posts) + .HasForeignKey(x => x.CategoryId) + .OnDelete(DeleteBehavior.Restrict); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "BlogComments", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Content).IsRequired().HasMaxLength(2048); + + b.HasOne(x => x.Post) + .WithMany(x => x.Comments) + .HasForeignKey(x => x.PostId) + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne(x => x.Parent) + .WithMany(x => x.Replies) + .HasForeignKey(x => x.ParentId) + .OnDelete(DeleteBehavior.Restrict); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "BlogPostTags", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Tag).IsRequired().HasMaxLength(64); + + b.HasIndex(x => new { x.PostId, x.Tag }).IsUnique(); + b.HasIndex(x => x.Tag); + + b.HasOne(x => x.Post) + .WithMany(x => x.Tags) + .HasForeignKey(x => x.PostId) + .OnDelete(DeleteBehavior.Cascade); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "BlogPostLikes", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.HasIndex(x => new { x.PostId, x.UserId }).IsUnique(); + + b.HasOne(x => x.Post) + .WithMany(x => x.Likes) + .HasForeignKey(x => x.PostId) + .OnDelete(DeleteBehavior.Cascade); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "BlogCommentLikes", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.HasIndex(x => new { x.CommentId, x.UserId }).IsUnique(); + + b.HasOne(x => x.Comment) + .WithMany(x => x.Likes) + .HasForeignKey(x => x.CommentId) + .OnDelete(DeleteBehavior.Cascade); + }); + + // Forum Entity Configurations + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "ForumCategories", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Name).IsRequired().HasMaxLength(128); + b.Property(x => x.Description).HasMaxLength(512); + b.Property(x => x.Icon).HasMaxLength(64); + + b.HasIndex(x => x.DisplayOrder); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "ForumTopics", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Title).IsRequired().HasMaxLength(256); + b.Property(x => x.Content).IsRequired(); + + b.HasIndex(x => x.CategoryId); + b.HasIndex(x => x.IsPinned); + b.HasIndex(x => x.LastPostDate); + + b.HasOne(x => x.Category) + .WithMany(x => x.Topics) + .HasForeignKey(x => x.CategoryId) + .OnDelete(DeleteBehavior.Restrict); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "ForumPosts", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Content).IsRequired(); + + b.HasIndex(x => x.TopicId); + + b.HasOne(x => x.Topic) + .WithMany(x => x.Posts) + .HasForeignKey(x => x.TopicId) + .OnDelete(DeleteBehavior.Cascade); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "ForumTopicTags", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.Property(x => x.Tag).IsRequired().HasMaxLength(64); + + b.HasIndex(x => new { x.TopicId, x.Tag }).IsUnique(); + b.HasIndex(x => x.Tag); + + b.HasOne(x => x.Topic) + .WithMany(x => x.Tags) + .HasForeignKey(x => x.TopicId) + .OnDelete(DeleteBehavior.Cascade); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "ForumTopicLikes", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.HasIndex(x => new { x.TopicId, x.UserId }).IsUnique(); + + b.HasOne(x => x.Topic) + .WithMany(x => x.Likes) + .HasForeignKey(x => x.TopicId) + .OnDelete(DeleteBehavior.Cascade); + }); + + builder.Entity(b => + { + b.ToTable(PlatformConsts.DbTablePrefix + "ForumPostLikes", PlatformConsts.DbSchema); + b.ConfigureByConvention(); + + b.HasIndex(x => new { x.PostId, x.UserId }).IsUnique(); + + b.HasOne(x => x.Post) + .WithMany(x => x.Likes) + .HasForeignKey(x => x.PostId) + .OnDelete(DeleteBehavior.Cascade); + }); } } diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20250619131606_AddBlogForumEntities.Designer.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20250619131606_AddBlogForumEntities.Designer.cs new file mode 100644 index 00000000..d9689944 --- /dev/null +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20250619131606_AddBlogForumEntities.Designer.cs @@ -0,0 +1,5449 @@ +// +using System; +using Kurs.Platform.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace Kurs.Platform.Migrations +{ + [DbContext(typeof(PlatformDbContext))] + [Migration("20250619131606_AddBlogForumEntities")] + partial class AddBlogForumEntities + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("ContactTag", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Category") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("PContactTag", (string)null); + }); + + modelBuilder.Entity("ContactTitle", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Abbreviation") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("PContactTitle", (string)null); + }); + + modelBuilder.Entity("Kurs.Languages.Entities.Language", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("MultipleCultures") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoLetterISOLanguageName") + .HasColumnType("nvarchar(max)"); + + b.Property("UiCultureName") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.HasKey("Id"); + + b.ToTable("PLanguage", (string)null); + }); + + modelBuilder.Entity("Kurs.Languages.Entities.LanguageKey", b => + { + b.Property("ResourceName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.HasKey("ResourceName", "Key"); + + b.ToTable("PLanguageKey", (string)null); + }); + + modelBuilder.Entity("Kurs.Languages.Entities.LanguageText", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("Key") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ResourceName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.HasKey("Id"); + + b.HasIndex("ResourceName", "Key"); + + b.ToTable("PLanguageText", (string)null); + }); + + modelBuilder.Entity("Kurs.MailQueue.Domain.Entities.BackgroundWorker_MailQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Attachment") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("AttachmentParameter") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("AwsMessageId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("From") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("MailParameter") + .HasMaxLength(8000) + .HasColumnType("nvarchar(max)"); + + b.Property("RelatedRecordId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("SendStatus") + .HasColumnType("bit"); + + b.Property("SendTime") + .HasColumnType("datetime2"); + + b.Property("Table") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("TableParameter") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier"); + + b.Property("To") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("PBackgroundWorker_MailQueue", (string)null); + }); + + modelBuilder.Entity("Kurs.MailQueue.Domain.Entities.BackgroundWorker_MailQueueEvents", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AwsMessageId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Event") + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("MailAddress") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ResponseDescription") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PBackgroundWorker_MailQueueEvents", (string)null); + }); + + modelBuilder.Entity("Kurs.MailQueue.Domain.Entities.BackgroundWorker_MailQueueTableFormat", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Caption") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ColumnName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Css") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DataFormat") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("DataType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("FooterCss") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("HeaderCss") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("IsHidden") + .HasColumnType("bit"); + + b.Property("IsProtected") + .HasColumnType("bit"); + + b.Property("Order") + .HasColumnType("smallint"); + + b.Property("SubTotal") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TableName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Width") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "TableName", "Order" }, "IX_MailQueueTableFormat") + .IsUnique(); + + b.ToTable("PBackgroundWorker_MailQueueTableFormat", (string)null); + }); + + modelBuilder.Entity("Kurs.Notifications.Entities.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Identifier") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsRead") + .HasColumnType("bit"); + + b.Property("IsSent") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Message") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NotificationChannel") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("NotificationRuleId") + .HasColumnType("uniqueidentifier"); + + b.Property("NotificationType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ReadTime") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.ToTable("PNotification", (string)null); + }); + + modelBuilder.Entity("Kurs.Notifications.Entities.NotificationRule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Channel") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsCustomized") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsFixed") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("NotificationType") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("RecipientId") + .HasColumnType("nvarchar(max)"); + + b.Property("RecipientType") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PNotificationRule", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogCategory", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("Icon") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PostCount") + .HasColumnType("int"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Slug"); + + b.ToTable("PBlogCategories", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogComment", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.HasIndex("PostId"); + + b.ToTable("PBlogComments", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogCommentLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CommentId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("CommentId", "UserId") + .IsUnique(); + + b.ToTable("PBlogCommentLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPost", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("CategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("CommentCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CoverImage") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsPublished") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("PublishedAt") + .HasColumnType("datetime2"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Summary") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ViewCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("IsPublished"); + + b.HasIndex("PublishedAt"); + + b.HasIndex("Slug"); + + b.ToTable("PBlogPosts", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("PostId", "UserId") + .IsUnique(); + + b.ToTable("PBlogPostLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostTag", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("Tag") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Tag"); + + b.HasIndex("PostId", "Tag") + .IsUnique(); + + b.ToTable("PBlogPostTags", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.AiBot", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("BotName") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PAiBot", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.BackgroundWorker", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AfterSp") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("BeforeSp") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("Cron") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("DataSourceCode") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Options") + .HasColumnType("nvarchar(max)"); + + b.Property("WorkerType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PBackgroundWorker", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Bank", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AddressLine1") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("AddressLine2") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("City") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Country") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("District") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Email") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IdentifierCode") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Phone") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("PostalCode") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.HasKey("Id"); + + b.ToTable("Banks"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.BankAccount", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("AccountOwner") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("BankId") + .HasColumnType("uniqueidentifier"); + + b.Property("CanTransferMoney") + .HasColumnType("bit"); + + b.Property("Company") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CurrencyId") + .HasColumnType("uniqueidentifier"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.HasIndex("BankId"); + + b.HasIndex("CurrencyId"); + + b.ToTable("BankAccounts"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Branch", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Address") + .HasColumnType("nvarchar(max)"); + + b.Property("Address2") + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .HasColumnType("nvarchar(max)"); + + b.Property("Code") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("District") + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("Fax") + .HasColumnType("bigint"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Mobile") + .HasColumnType("bigint"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("Phone") + .HasColumnType("bigint"); + + b.Property("PostalCode") + .HasColumnType("nvarchar(max)"); + + b.Property("TaxOffice") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("VknTckn") + .HasColumnType("bigint"); + + b.Property("Website") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PBranch", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.BranchUsers", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("BranchId") + .HasColumnType("uniqueidentifier"); + + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "BranchId"); + + b.ToTable("PBranchUsers", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Chart", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AdaptiveLayoutJson") + .HasColumnType("nvarchar(max)"); + + b.Property("AnimationJson") + .HasColumnType("nvarchar(max)"); + + b.Property("AnnotationsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("ArgumentAxisJson") + .HasColumnType("nvarchar(max)"); + + b.Property("ChartCode") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CommonAnnotationsSettingsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CommonAxisSettingsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CommonJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CommonPaneSettingsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CommonSeriesSettingsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CrosshairJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CultureName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(max)") + .HasDefaultValue("en"); + + b.Property("DataSourceCode") + .HasColumnType("nvarchar(max)"); + + b.Property("DataSourceJson") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("ExportJson") + .HasColumnType("nvarchar(max)"); + + b.Property("IsBranch") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsOrganizationUnit") + .HasColumnType("bit"); + + b.Property("IsTenant") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LegendJson") + .HasColumnType("nvarchar(max)"); + + b.Property("MarginJson") + .HasColumnType("nvarchar(max)"); + + b.Property("PanesJson") + .HasColumnType("nvarchar(max)"); + + b.Property("PermissionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(max)"); + + b.Property("ScrollBarJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SeriesJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SizeJson") + .HasColumnType("nvarchar(max)"); + + b.Property("TitleJson") + .HasColumnType("nvarchar(max)"); + + b.Property("TooltipJson") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("nvarchar(max)"); + + b.Property("ValueAxisJson") + .HasColumnType("nvarchar(max)"); + + b.Property("ZoomAndPanJson") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PChart", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Country", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CurrencyCode") + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("GroupName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PhoneCode") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.Property("StateRequired") + .HasColumnType("bit"); + + b.Property("TaxLabel") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ZipRequired") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("Code") + .IsUnique(); + + b.HasIndex("GroupName"); + + b.ToTable("PCountry", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.CountryGroup", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("PCountryGroup", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Currency", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastUpdated") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Rate") + .HasColumnType("decimal(18,6)"); + + b.Property("Symbol") + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.HasKey("Id"); + + b.ToTable("PCurrency", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.DataSource", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ConnectionString") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DataSourceType") + .HasColumnType("int"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.ToTable("PDataSource", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.GlobalSearch", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Group") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("System") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Term") + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .HasColumnType("nvarchar(max)"); + + b.Property("Weight") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PGlobalSearch", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.IpRestriction", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IP") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ResourceId") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("ResourceType") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("PIpRestriction", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.ListForm", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ColumnOptionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CommandColumnJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomJsSourcesJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomStyleSourcesJson") + .HasColumnType("nvarchar(max)"); + + b.Property("DataSourceCode") + .HasColumnType("nvarchar(max)"); + + b.Property("DefaultFilter") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleteCommand") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleteFieldsDefaultValueJson") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleteServiceAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("EditingFormJson") + .HasColumnType("nvarchar(max)"); + + b.Property("EditingOptionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("FilterPanelJson") + .HasColumnType("nvarchar(max)"); + + b.Property("FilterRowJson") + .HasColumnType("nvarchar(max)"); + + b.Property("FormFieldsDefaultValueJson") + .HasColumnType("nvarchar(max)"); + + b.Property("GroupPanelJson") + .HasColumnType("nvarchar(max)"); + + b.Property("HeaderFilterJson") + .HasColumnType("nvarchar(max)"); + + b.Property("Height") + .HasColumnType("int"); + + b.Property("InsertCommand") + .HasColumnType("nvarchar(max)"); + + b.Property("InsertFieldsDefaultValueJson") + .HasColumnType("nvarchar(max)"); + + b.Property("InsertServiceAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("IsBranch") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsOrganizationUnit") + .HasColumnType("bit"); + + b.Property("IsSubForm") + .HasColumnType("bit"); + + b.Property("IsTenant") + .HasColumnType("bit"); + + b.Property("KeyFieldDbSourceType") + .HasColumnType("int"); + + b.Property("KeyFieldName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ListFormCode") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ListFormType") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("PageSize") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(10); + + b.Property("PagerOptionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("PermissionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SearchPanelJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SelectCommand") + .HasColumnType("nvarchar(max)"); + + b.Property("SelectCommandType") + .HasColumnType("int"); + + b.Property("SelectFieldsDefaultValueJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SelectionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SortMode") + .HasColumnType("nvarchar(max)"); + + b.Property("StateStoringJson") + .HasColumnType("nvarchar(max)"); + + b.Property("SubFormsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("TableName") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateCommand") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateFieldsDefaultValueJson") + .HasColumnType("nvarchar(max)"); + + b.Property("UpdateServiceAddress") + .HasColumnType("nvarchar(max)"); + + b.Property("Width") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PListForm", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.ListFormCustomization", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CustomizationData") + .HasColumnType("nvarchar(max)"); + + b.Property("CustomizationType") + .HasColumnType("int"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("FilterName") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ListFormCode") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ListFormCode"); + + b.ToTable("PListFormCustomization", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.ListFormField", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Alignment") + .HasColumnType("nvarchar(max)"); + + b.Property("AllowSearch") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("BandName") + .HasColumnType("nvarchar(max)"); + + b.Property("CaptionName") + .HasColumnType("nvarchar(max)"); + + b.Property("ColumnCssClass") + .HasColumnType("nvarchar(max)"); + + b.Property("ColumnCssValue") + .HasColumnType("nvarchar(max)"); + + b.Property("ColumnCustomizationJson") + .HasColumnType("nvarchar(max)"); + + b.Property("ColumnFilterJson") + .HasColumnType("nvarchar(max)"); + + b.Property("ColumnHeaderJson") + .HasColumnType("nvarchar(max)"); + + b.Property("ColumnStylingJson") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CultureName") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("EditingJson") + .HasColumnType("nvarchar(max)"); + + b.Property("EditorOptions") + .HasColumnType("nvarchar(max)"); + + b.Property("FieldName") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Format") + .HasColumnType("nvarchar(max)"); + + b.Property("GroupSummaryJson") + .HasColumnType("nvarchar(max)"); + + b.Property("GroupingJson") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JoinTableJson") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ListFormCode") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("ListOrderNo") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(30); + + b.Property("LookupJson") + .HasColumnType("nvarchar(max)"); + + b.Property("PermissionJson") + .HasColumnType("nvarchar(max)"); + + b.Property("PivotSettingsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(max)"); + + b.Property("SortDirection") + .HasColumnType("nvarchar(max)"); + + b.Property("SortIndex") + .HasColumnType("int"); + + b.Property("SourceDbType") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(16); + + b.Property("TotalSummaryJson") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("nvarchar(max)"); + + b.Property("ValidationRuleJson") + .HasColumnType("nvarchar(max)"); + + b.Property("Visible") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("Width") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("ListFormCode"); + + b.ToTable("PListFormField", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Menu", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("CssClass") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CultureName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ElementId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Icon") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsDisabled") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("ParentCode") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("RequiredPermissionName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("RoleId") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Target") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Url") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UserId") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.ToTable("PMenu", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.PublicApi", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DataSourceCode") + .HasColumnType("nvarchar(max)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Method") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("ParametersJson") + .HasColumnType("nvarchar(max)"); + + b.Property("PermissionsJson") + .HasColumnType("nvarchar(max)"); + + b.Property("Sql") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Url") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("PPublicApi", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Sector", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("FullName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("PSector", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.State", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.Property("CountryCode") + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("CountryCode", "Code") + .IsUnique() + .HasFilter("[CountryCode] IS NOT NULL AND [Code] IS NOT NULL"); + + b.ToTable("PState", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Uom", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CategoryName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Ratio") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("Rounding") + .HasPrecision(18, 6) + .HasColumnType("decimal(18,6)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.HasKey("Id"); + + b.HasIndex("CategoryName"); + + b.ToTable("PUom", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.UomCategory", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("PUomCategory", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumCategory", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("Icon") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPostDate") + .HasColumnType("datetime2"); + + b.Property("LastPostId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastPostUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PostCount") + .HasColumnType("int"); + + b.Property("Slug") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DisplayOrder"); + + b.ToTable("PForumCategories", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPost", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsAcceptedAnswer") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TopicId"); + + b.ToTable("PForumPosts", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPostLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("PostId", "UserId") + .IsUnique(); + + b.ToTable("PForumPostLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopic", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("CategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("IsPinned") + .HasColumnType("bit"); + + b.Property("IsSolved") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPostDate") + .HasColumnType("datetime2"); + + b.Property("LastPostId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastPostUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("ReplyCount") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ViewCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("IsPinned"); + + b.HasIndex("LastPostDate"); + + b.ToTable("PForumTopics", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TopicId", "UserId") + .IsUnique(); + + b.ToTable("PForumTopicLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicTag", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Tag") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Tag"); + + b.HasIndex("TopicId", "Tag") + .IsUnique(); + + b.ToTable("PForumTopicTags", (string)null); + }); + + modelBuilder.Entity("Kurs.Settings.Entities.SettingDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DataType") + .IsRequired() + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DescriptionKey") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("MainGroupKey") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("NameKey") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Order") + .HasColumnType("int"); + + b.Property("Providers") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("RequiredPermissionName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SelectOptions") + .HasColumnType("nvarchar(max)"); + + b.Property("SubGroupKey") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("PSettingDefinition", (string)null); + }); + + modelBuilder.Entity("Skill", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SkillTypeId") + .HasColumnType("uniqueidentifier"); + + b.Property("TypeName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("SkillTypeId"); + + b.ToTable("PSkill", (string)null); + }); + + modelBuilder.Entity("SkillLevel", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDefault") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Progress") + .HasColumnType("int"); + + b.Property("SkillTypeId") + .HasColumnType("uniqueidentifier"); + + b.Property("TypeName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("SkillTypeId"); + + b.ToTable("PSkillLevel", (string)null); + }); + + modelBuilder.Entity("SkillType", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("PSkillType", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasColumnType("nvarchar(max)"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorTenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ImpersonatorTenantName"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorUserId"); + + b.Property("ImpersonatorUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ImpersonatorUserName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("TenantName"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("datetime2") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("tinyint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EntityChangeId") + .HasColumnType("uniqueidentifier"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("nvarchar(max)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LastTryTime") + .HasColumnType("datetime2"); + + b.Property("NextTryTime") + .HasColumnType("datetime2"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Device") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("DeviceInfo") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IpAddresses") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("LastAccessed") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("SignedIn") + .HasColumnType("datetime2"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Device"); + + b.HasIndex("SessionId"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSessions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("IsVerified") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPasswordChangeTime") + .HasColumnType("datetimeoffset"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("LoginEndDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("RocketUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("ShouldChangePasswordOnNextLogin") + .HasColumnType("bit"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.ToTable("AbpUserDelegations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ClientSecret") + .HasColumnType("nvarchar(max)"); + + b.Property("ClientType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("ClientUri") + .HasColumnType("nvarchar(max)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("JsonWebKeySet") + .HasColumnType("nvarchar(max)"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasColumnType("nvarchar(max)"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedirectUris") + .HasColumnType("nvarchar(max)"); + + b.Property("Requirements") + .HasColumnType("nvarchar(max)"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("OpenIddictApplications", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Scopes") + .HasColumnType("nvarchar(max)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictAuthorizations", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Scopes.OpenIddictScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnType("nvarchar(max)"); + + b.Property("Descriptions") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("DisplayNames") + .HasColumnType("nvarchar(max)"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("Resources") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("OpenIddictScopes", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationId") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Payload") + .HasColumnType("nvarchar(max)"); + + b.Property("Properties") + .HasColumnType("nvarchar(max)"); + + b.Property("RedemptionDate") + .HasColumnType("datetime2"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("nvarchar(400)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationId"); + + b.HasIndex("ReferenceId"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type"); + + b.ToTable("OpenIddictTokens", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("bit"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[TenantId] IS NOT NULL"); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique() + .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL"); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("DefaultValue") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsEncrypted") + .HasColumnType("bit"); + + b.Property("IsInherited") + .HasColumnType("bit"); + + b.Property("IsVisibleToClients") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Providers") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpSettingDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Address") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Address2") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("City") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("District") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EntityVersion") + .HasColumnType("int"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Fax") + .HasColumnType("bigint"); + + b.Property("InstitutionName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(true); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Mobile") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Phone") + .HasColumnType("bigint"); + + b.Property("PostalCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("TaxOffice") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("VknTckn") + .HasColumnType("bigint"); + + b.Property("Website") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("Kurs.Languages.Entities.LanguageText", b => + { + b.HasOne("Kurs.Languages.Entities.LanguageKey", null) + .WithMany("Texts") + .HasForeignKey("ResourceName", "Key") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogComment", b => + { + b.HasOne("Kurs.Platform.Blog.BlogComment", "Parent") + .WithMany("Replies") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Kurs.Platform.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogCommentLike", b => + { + b.HasOne("Kurs.Platform.Blog.BlogComment", "Comment") + .WithMany("Likes") + .HasForeignKey("CommentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Comment"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPost", b => + { + b.HasOne("Kurs.Platform.Blog.BlogCategory", "Category") + .WithMany("Posts") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostLike", b => + { + b.HasOne("Kurs.Platform.Blog.BlogPost", "Post") + .WithMany("Likes") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostTag", b => + { + b.HasOne("Kurs.Platform.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.BankAccount", b => + { + b.HasOne("Kurs.Platform.Entities.Bank", "Bank") + .WithMany() + .HasForeignKey("BankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Kurs.Platform.Entities.Currency", "Currency") + .WithMany() + .HasForeignKey("CurrencyId"); + + b.Navigation("Bank"); + + b.Navigation("Currency"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Country", b => + { + b.HasOne("Kurs.Platform.Entities.CountryGroup", null) + .WithMany() + .HasForeignKey("GroupName") + .HasPrincipalKey("Name") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.ListFormCustomization", b => + { + b.HasOne("Kurs.Platform.Entities.ListForm", null) + .WithMany() + .HasForeignKey("ListFormCode") + .HasPrincipalKey("ListFormCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.ListFormField", b => + { + b.HasOne("Kurs.Platform.Entities.ListForm", null) + .WithMany() + .HasForeignKey("ListFormCode") + .HasPrincipalKey("ListFormCode") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.State", b => + { + b.HasOne("Kurs.Platform.Entities.Country", "Country") + .WithMany("States") + .HasForeignKey("CountryCode") + .HasPrincipalKey("Code") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Country"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Uom", b => + { + b.HasOne("Kurs.Platform.Entities.UomCategory", "UomCategory") + .WithMany("Units") + .HasForeignKey("CategoryName") + .HasPrincipalKey("Name") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("UomCategory"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPost", b => + { + b.HasOne("Kurs.Platform.Forum.ForumTopic", "Topic") + .WithMany("Posts") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Topic"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPostLike", b => + { + b.HasOne("Kurs.Platform.Forum.ForumPost", "Post") + .WithMany("Likes") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopic", b => + { + b.HasOne("Kurs.Platform.Forum.ForumCategory", "Category") + .WithMany("Topics") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicLike", b => + { + b.HasOne("Kurs.Platform.Forum.ForumTopic", "Topic") + .WithMany("Likes") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Topic"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicTag", b => + { + b.HasOne("Kurs.Platform.Forum.ForumTopic", "Topic") + .WithMany("Tags") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Topic"); + }); + + modelBuilder.Entity("Skill", b => + { + b.HasOne("SkillType", null) + .WithMany("Skills") + .HasForeignKey("SkillTypeId"); + }); + + modelBuilder.Entity("SkillLevel", b => + { + b.HasOne("SkillType", null) + .WithMany("Levels") + .HasForeignKey("SkillTypeId"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + }); + + modelBuilder.Entity("Volo.Abp.OpenIddict.Tokens.OpenIddictToken", b => + { + b.HasOne("Volo.Abp.OpenIddict.Applications.OpenIddictApplication", null) + .WithMany() + .HasForeignKey("ApplicationId"); + + b.HasOne("Volo.Abp.OpenIddict.Authorizations.OpenIddictAuthorization", null) + .WithMany() + .HasForeignKey("AuthorizationId"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.TenantConnectionString", b => + { + b.HasOne("Volo.Abp.TenantManagement.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Kurs.Languages.Entities.LanguageKey", b => + { + b.Navigation("Texts"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogCategory", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogComment", b => + { + b.Navigation("Likes"); + + b.Navigation("Replies"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPost", b => + { + b.Navigation("Comments"); + + b.Navigation("Likes"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.Country", b => + { + b.Navigation("States"); + }); + + modelBuilder.Entity("Kurs.Platform.Entities.UomCategory", b => + { + b.Navigation("Units"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumCategory", b => + { + b.Navigation("Topics"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPost", b => + { + b.Navigation("Likes"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopic", b => + { + b.Navigation("Likes"); + + b.Navigation("Posts"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("SkillType", b => + { + b.Navigation("Levels"); + + b.Navigation("Skills"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.TenantManagement.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20250619131606_AddBlogForumEntities.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20250619131606_AddBlogForumEntities.cs new file mode 100644 index 00000000..27a3f697 --- /dev/null +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/20250619131606_AddBlogForumEntities.cs @@ -0,0 +1,491 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Kurs.Platform.Migrations +{ + /// + public partial class AddBlogForumEntities : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "PBlogCategories", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Slug = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Description = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + Icon = table.Column(type: "nvarchar(max)", nullable: true), + DisplayOrder = table.Column(type: "int", nullable: false), + IsActive = table.Column(type: "bit", nullable: false), + PostCount = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PBlogCategories", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PForumCategories", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Name = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Slug = table.Column(type: "nvarchar(max)", nullable: true), + Description = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + Icon = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + DisplayOrder = table.Column(type: "int", nullable: false), + IsActive = table.Column(type: "bit", nullable: false), + IsLocked = table.Column(type: "bit", nullable: false), + TopicCount = table.Column(type: "int", nullable: false), + PostCount = table.Column(type: "int", nullable: false), + LastPostId = table.Column(type: "uniqueidentifier", nullable: true), + LastPostDate = table.Column(type: "datetime2", nullable: true), + LastPostUserId = table.Column(type: "uniqueidentifier", nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PForumCategories", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PBlogPosts", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Title = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Slug = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Content = table.Column(type: "nvarchar(max)", nullable: false), + Summary = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), + CoverImage = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: true), + CategoryId = table.Column(type: "uniqueidentifier", nullable: false), + AuthorId = table.Column(type: "uniqueidentifier", nullable: false), + ViewCount = table.Column(type: "int", nullable: false), + LikeCount = table.Column(type: "int", nullable: false), + CommentCount = table.Column(type: "int", nullable: false), + IsPublished = table.Column(type: "bit", nullable: false), + PublishedAt = table.Column(type: "datetime2", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PBlogPosts", x => x.Id); + table.ForeignKey( + name: "FK_PBlogPosts_PBlogCategories_CategoryId", + column: x => x.CategoryId, + principalTable: "PBlogCategories", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PForumTopics", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + Title = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Content = table.Column(type: "nvarchar(max)", nullable: false), + CategoryId = table.Column(type: "uniqueidentifier", nullable: false), + AuthorId = table.Column(type: "uniqueidentifier", nullable: false), + ViewCount = table.Column(type: "int", nullable: false), + ReplyCount = table.Column(type: "int", nullable: false), + LikeCount = table.Column(type: "int", nullable: false), + IsPinned = table.Column(type: "bit", nullable: false), + IsLocked = table.Column(type: "bit", nullable: false), + IsSolved = table.Column(type: "bit", nullable: false), + LastPostId = table.Column(type: "uniqueidentifier", nullable: true), + LastPostDate = table.Column(type: "datetime2", nullable: true), + LastPostUserId = table.Column(type: "uniqueidentifier", nullable: true), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: false), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PForumTopics", x => x.Id); + table.ForeignKey( + name: "FK_PForumTopics_PForumCategories_CategoryId", + column: x => x.CategoryId, + principalTable: "PForumCategories", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "PBlogComments", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + PostId = table.Column(type: "uniqueidentifier", nullable: false), + Content = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false), + AuthorId = table.Column(type: "uniqueidentifier", nullable: false), + ParentId = table.Column(type: "uniqueidentifier", nullable: true), + LikeCount = table.Column(type: "int", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PBlogComments", x => x.Id); + table.ForeignKey( + name: "FK_PBlogComments_PBlogComments_ParentId", + column: x => x.ParentId, + principalTable: "PBlogComments", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_PBlogComments_PBlogPosts_PostId", + column: x => x.PostId, + principalTable: "PBlogPosts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PBlogPostLikes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + PostId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PBlogPostLikes", x => x.Id); + table.ForeignKey( + name: "FK_PBlogPostLikes_PBlogPosts_PostId", + column: x => x.PostId, + principalTable: "PBlogPosts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PBlogPostTags", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + PostId = table.Column(type: "uniqueidentifier", nullable: false), + Tag = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PBlogPostTags", x => x.Id); + table.ForeignKey( + name: "FK_PBlogPostTags_PBlogPosts_PostId", + column: x => x.PostId, + principalTable: "PBlogPosts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PForumPosts", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + TopicId = table.Column(type: "uniqueidentifier", nullable: false), + Content = table.Column(type: "nvarchar(max)", nullable: false), + AuthorId = table.Column(type: "uniqueidentifier", nullable: false), + LikeCount = table.Column(type: "int", nullable: false), + IsAcceptedAnswer = table.Column(type: "bit", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true), + LastModificationTime = table.Column(type: "datetime2", nullable: true), + LastModifierId = table.Column(type: "uniqueidentifier", nullable: true), + IsDeleted = table.Column(type: "bit", nullable: false, defaultValue: false), + DeleterId = table.Column(type: "uniqueidentifier", nullable: true), + DeletionTime = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PForumPosts", x => x.Id); + table.ForeignKey( + name: "FK_PForumPosts_PForumTopics_TopicId", + column: x => x.TopicId, + principalTable: "PForumTopics", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PForumTopicLikes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + TopicId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PForumTopicLikes", x => x.Id); + table.ForeignKey( + name: "FK_PForumTopicLikes_PForumTopics_TopicId", + column: x => x.TopicId, + principalTable: "PForumTopics", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PForumTopicTags", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + TopicId = table.Column(type: "uniqueidentifier", nullable: false), + Tag = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PForumTopicTags", x => x.Id); + table.ForeignKey( + name: "FK_PForumTopicTags_PForumTopics_TopicId", + column: x => x.TopicId, + principalTable: "PForumTopics", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PBlogCommentLikes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + CommentId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PBlogCommentLikes", x => x.Id); + table.ForeignKey( + name: "FK_PBlogCommentLikes_PBlogComments_CommentId", + column: x => x.CommentId, + principalTable: "PBlogComments", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PForumPostLikes", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + TenantId = table.Column(type: "uniqueidentifier", nullable: true), + PostId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PForumPostLikes", x => x.Id); + table.ForeignKey( + name: "FK_PForumPostLikes_PForumPosts_PostId", + column: x => x.PostId, + principalTable: "PForumPosts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_PBlogCategories_Slug", + table: "PBlogCategories", + column: "Slug"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogCommentLikes_CommentId_UserId", + table: "PBlogCommentLikes", + columns: new[] { "CommentId", "UserId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PBlogComments_ParentId", + table: "PBlogComments", + column: "ParentId"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogComments_PostId", + table: "PBlogComments", + column: "PostId"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPostLikes_PostId_UserId", + table: "PBlogPostLikes", + columns: new[] { "PostId", "UserId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPosts_CategoryId", + table: "PBlogPosts", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPosts_IsPublished", + table: "PBlogPosts", + column: "IsPublished"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPosts_PublishedAt", + table: "PBlogPosts", + column: "PublishedAt"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPosts_Slug", + table: "PBlogPosts", + column: "Slug"); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPostTags_PostId_Tag", + table: "PBlogPostTags", + columns: new[] { "PostId", "Tag" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PBlogPostTags_Tag", + table: "PBlogPostTags", + column: "Tag"); + + migrationBuilder.CreateIndex( + name: "IX_PForumCategories_DisplayOrder", + table: "PForumCategories", + column: "DisplayOrder"); + + migrationBuilder.CreateIndex( + name: "IX_PForumPostLikes_PostId_UserId", + table: "PForumPostLikes", + columns: new[] { "PostId", "UserId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PForumPosts_TopicId", + table: "PForumPosts", + column: "TopicId"); + + migrationBuilder.CreateIndex( + name: "IX_PForumTopicLikes_TopicId_UserId", + table: "PForumTopicLikes", + columns: new[] { "TopicId", "UserId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_PForumTopics_CategoryId", + table: "PForumTopics", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_PForumTopics_IsPinned", + table: "PForumTopics", + column: "IsPinned"); + + migrationBuilder.CreateIndex( + name: "IX_PForumTopics_LastPostDate", + table: "PForumTopics", + column: "LastPostDate"); + + migrationBuilder.CreateIndex( + name: "IX_PForumTopicTags_Tag", + table: "PForumTopicTags", + column: "Tag"); + + migrationBuilder.CreateIndex( + name: "IX_PForumTopicTags_TopicId_Tag", + table: "PForumTopicTags", + columns: new[] { "TopicId", "Tag" }, + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "PBlogCommentLikes"); + + migrationBuilder.DropTable( + name: "PBlogPostLikes"); + + migrationBuilder.DropTable( + name: "PBlogPostTags"); + + migrationBuilder.DropTable( + name: "PForumPostLikes"); + + migrationBuilder.DropTable( + name: "PForumTopicLikes"); + + migrationBuilder.DropTable( + name: "PForumTopicTags"); + + migrationBuilder.DropTable( + name: "PBlogComments"); + + migrationBuilder.DropTable( + name: "PForumPosts"); + + migrationBuilder.DropTable( + name: "PBlogPosts"); + + migrationBuilder.DropTable( + name: "PForumTopics"); + + migrationBuilder.DropTable( + name: "PBlogCategories"); + + migrationBuilder.DropTable( + name: "PForumCategories"); + } + } +} diff --git a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs index 793df2dc..bc27493a 100644 --- a/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs +++ b/api/src/Kurs.Platform.EntityFrameworkCore/Migrations/PlatformDbContextModelSnapshot.cs @@ -650,6 +650,340 @@ namespace Kurs.Platform.Migrations b.ToTable("PNotificationRule", (string)null); }); + modelBuilder.Entity("Kurs.Platform.Blog.BlogCategory", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("Icon") + .HasColumnType("nvarchar(max)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PostCount") + .HasColumnType("int"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Slug"); + + b.ToTable("PBlogCategories", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogComment", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.HasIndex("PostId"); + + b.ToTable("PBlogComments", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogCommentLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CommentId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("CommentId", "UserId") + .IsUnique(); + + b.ToTable("PBlogCommentLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPost", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("CategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("CommentCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CoverImage") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsPublished") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("PublishedAt") + .HasColumnType("datetime2"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Summary") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ViewCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("IsPublished"); + + b.HasIndex("PublishedAt"); + + b.HasIndex("Slug"); + + b.ToTable("PBlogPosts", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("PostId", "UserId") + .IsUnique(); + + b.ToTable("PBlogPostLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostTag", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("Tag") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Tag"); + + b.HasIndex("PostId", "Tag") + .IsUnique(); + + b.ToTable("PBlogPostTags", (string)null); + }); + modelBuilder.Entity("Kurs.Platform.Entities.AiBot", b => { b.Property("Id") @@ -2249,6 +2583,347 @@ namespace Kurs.Platform.Migrations b.ToTable("PUomCategory", (string)null); }); + modelBuilder.Entity("Kurs.Platform.Forum.ForumCategory", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("DisplayOrder") + .HasColumnType("int"); + + b.Property("Icon") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("IsActive") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPostDate") + .HasColumnType("datetime2"); + + b.Property("LastPostId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastPostUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("PostCount") + .HasColumnType("int"); + + b.Property("Slug") + .HasColumnType("nvarchar(max)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("DisplayOrder"); + + b.ToTable("PForumCategories", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPost", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("IsAcceptedAnswer") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TopicId"); + + b.ToTable("PForumPosts", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPostLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("PostId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("PostId", "UserId") + .IsUnique(); + + b.ToTable("PForumPostLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopic", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AuthorId") + .HasColumnType("uniqueidentifier"); + + b.Property("CategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("ExtraProperties") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsLocked") + .HasColumnType("bit"); + + b.Property("IsPinned") + .HasColumnType("bit"); + + b.Property("IsSolved") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LastPostDate") + .HasColumnType("datetime2"); + + b.Property("LastPostId") + .HasColumnType("uniqueidentifier"); + + b.Property("LastPostUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LikeCount") + .HasColumnType("int"); + + b.Property("ReplyCount") + .HasColumnType("int"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ViewCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("IsPinned"); + + b.HasIndex("LastPostDate"); + + b.ToTable("PForumTopics", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicLike", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("TopicId", "UserId") + .IsUnique(); + + b.ToTable("PForumTopicLikes", (string)null); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicTag", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Tag") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TopicId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("Tag"); + + b.HasIndex("TopicId", "Tag") + .IsUnique(); + + b.ToTable("PForumTopicTags", (string)null); + }); + modelBuilder.Entity("Kurs.Settings.Entities.SettingDefinition", b => { b.Property("Id") @@ -4322,6 +4997,68 @@ namespace Kurs.Platform.Migrations .OnDelete(DeleteBehavior.SetNull); }); + modelBuilder.Entity("Kurs.Platform.Blog.BlogComment", b => + { + b.HasOne("Kurs.Platform.Blog.BlogComment", "Parent") + .WithMany("Replies") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Kurs.Platform.Blog.BlogPost", "Post") + .WithMany("Comments") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Parent"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogCommentLike", b => + { + b.HasOne("Kurs.Platform.Blog.BlogComment", "Comment") + .WithMany("Likes") + .HasForeignKey("CommentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Comment"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPost", b => + { + b.HasOne("Kurs.Platform.Blog.BlogCategory", "Category") + .WithMany("Posts") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostLike", b => + { + b.HasOne("Kurs.Platform.Blog.BlogPost", "Post") + .WithMany("Likes") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPostTag", b => + { + b.HasOne("Kurs.Platform.Blog.BlogPost", "Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + modelBuilder.Entity("Kurs.Platform.Entities.BankAccount", b => { b.HasOne("Kurs.Platform.Entities.Bank", "Bank") @@ -4391,6 +5128,61 @@ namespace Kurs.Platform.Migrations b.Navigation("UomCategory"); }); + modelBuilder.Entity("Kurs.Platform.Forum.ForumPost", b => + { + b.HasOne("Kurs.Platform.Forum.ForumTopic", "Topic") + .WithMany("Posts") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Topic"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPostLike", b => + { + b.HasOne("Kurs.Platform.Forum.ForumPost", "Post") + .WithMany("Likes") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopic", b => + { + b.HasOne("Kurs.Platform.Forum.ForumCategory", "Category") + .WithMany("Topics") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicLike", b => + { + b.HasOne("Kurs.Platform.Forum.ForumTopic", "Topic") + .WithMany("Likes") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Topic"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopicTag", b => + { + b.HasOne("Kurs.Platform.Forum.ForumTopic", "Topic") + .WithMany("Tags") + .HasForeignKey("TopicId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Topic"); + }); + modelBuilder.Entity("Skill", b => { b.HasOne("SkillType", null) @@ -4552,6 +5344,27 @@ namespace Kurs.Platform.Migrations b.Navigation("Texts"); }); + modelBuilder.Entity("Kurs.Platform.Blog.BlogCategory", b => + { + b.Navigation("Posts"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogComment", b => + { + b.Navigation("Likes"); + + b.Navigation("Replies"); + }); + + modelBuilder.Entity("Kurs.Platform.Blog.BlogPost", b => + { + b.Navigation("Comments"); + + b.Navigation("Likes"); + + b.Navigation("Tags"); + }); + modelBuilder.Entity("Kurs.Platform.Entities.Country", b => { b.Navigation("States"); @@ -4562,6 +5375,25 @@ namespace Kurs.Platform.Migrations b.Navigation("Units"); }); + modelBuilder.Entity("Kurs.Platform.Forum.ForumCategory", b => + { + b.Navigation("Topics"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumPost", b => + { + b.Navigation("Likes"); + }); + + modelBuilder.Entity("Kurs.Platform.Forum.ForumTopic", b => + { + b.Navigation("Likes"); + + b.Navigation("Posts"); + + b.Navigation("Tags"); + }); + modelBuilder.Entity("SkillType", b => { b.Navigation("Levels"); diff --git a/company/README_API_INTEGRATION.md b/company/README_API_INTEGRATION.md new file mode 100644 index 00000000..5b3f4842 --- /dev/null +++ b/company/README_API_INTEGRATION.md @@ -0,0 +1,159 @@ +# Company Uygulaması API Entegrasyonu + +Bu dokümantasyon, Company uygulamasına yapılan API entegrasyonu, üyelik sistemi, forum ve dinamik blog özelliklerini açıklamaktadır. + +## 🚀 Yapılan Değişiklikler + +### 1. API Entegrasyonu +- **Axios** ve **React Query** kullanılarak API yapısı kuruldu +- API servis katmanı oluşturuldu (`/src/services/api/`) +- Interceptor'lar ile otomatik token yönetimi eklendi + +### 2. Üyelik Sistemi +- **Zustand** ile state management kuruldu +- Login ve Register sayfaları oluşturuldu +- JWT token tabanlı authentication sistemi entegre edildi +- Protected route yapısı kuruldu + +### 3. Forum Sistemi +- Kapsamlı forum sayfası oluşturuldu +- Kategori, konu ve mesaj yönetimi +- Like, pin, lock gibi özellikler +- Etiket sistemi + +### 4. Dinamik Blog +- Static blog yapısı dinamik hale getirildi +- Kategori filtreleme +- Arama özelliği +- Sayfalama (pagination) +- Etiket sistemi + +## 📦 Yeni Eklenen Paketler + +```json +{ + "axios": "^1.6.5", + "@tanstack/react-query": "^5.17.9", + "zustand": "^4.4.7", + "react-hook-form": "^7.48.2", + "date-fns": "^3.2.0", + "react-markdown": "^9.0.1", + "react-hot-toast": "^2.4.1" +} +``` + +## 🛠️ Kurulum + +1. Paketleri yükleyin: +```bash +cd company +npm install +``` + +2. Environment değişkenlerini ayarlayın: +```env +VITE_API_URL=http://localhost:44328 +``` + +## 📁 Yeni Dosya Yapısı + +``` +company/src/ +├── services/ +│ └── api/ +│ ├── config.ts # Axios yapılandırması +│ ├── auth.service.ts # Authentication servisi +│ ├── blog.service.ts # Blog API servisi +│ └── forum.service.ts # Forum API servisi +├── store/ +│ └── authStore.ts # Zustand auth store +├── pages/ +│ ├── Login.tsx # Giriş sayfası +│ ├── Register.tsx # Kayıt sayfası +│ ├── Forum.tsx # Forum ana sayfası +│ └── Blog.tsx # Dinamik blog sayfası (güncellendi) +└── components/ + └── layout/ + └── Header.tsx # Auth butonları eklendi +``` + +## 🔐 Authentication Akışı (UI Uygulaması ile Aynı) + +1. Kullanıcı login sayfasından giriş yapar +2. OAuth2 `/connect/token` endpoint'i kullanılarak token alınır +3. Access token ve refresh token localStorage'a kaydedilir +4. `/api/abp/application-configuration` endpoint'inden kullanıcı bilgileri çekilir +5. Axios interceptor ile her istekte: + - Authorization header'a Bearer token eklenir + - `__tenant` header'a tenant ID eklenir (multi-tenancy desteği) +6. Protected route'lar için authentication kontrolü yapılır +7. Token expire olduğunda refresh token ile yenilenir +8. Refresh token da expire olduysa otomatik logout + +### OAuth2 Parametreleri +- **grant_type**: password +- **scope**: offline_access Platform +- **client_id**: Platform_App +- **client_secret**: 1q2w3e* + +## 🌟 Özellikler + +### Forum +- Kategori bazlı konu listeleme +- Yeni konu açma +- Konulara cevap yazma +- Like/Unlike +- Pin/Unpin (moderatör) +- Lock/Unlock (moderatör) +- Çözüldü olarak işaretleme +- Etiket sistemi +- Arama özelliği + +### Blog +- Dinamik içerik yönetimi +- Kategori filtreleme +- Arama +- Sayfalama +- Yorum sistemi +- Like sistemi +- Etiketler + +## 🔄 API Endpoints + +### Authentication (UI ile Aynı Endpoint'ler) +- `POST /connect/token` - OAuth2 token endpoint (Login & Refresh) +- `POST /api/account/register` - Register +- `GET /api/abp/application-configuration` - Current user & app config + +### Blog +- `GET /api/app/blog/posts` - Blog listesi +- `GET /api/app/blog/posts/:id` - Blog detay +- `GET /api/app/blog/categories` - Kategoriler +- `POST /api/app/blog/comments` - Yorum ekle + +### Forum +- `GET /api/app/forum/categories` - Forum kategorileri +- `GET /api/app/forum/topics` - Konu listesi +- `POST /api/app/forum/topics` - Yeni konu +- `GET /api/app/forum/topics/:id/posts` - Konu mesajları +- `POST /api/app/forum/posts` - Yeni mesaj + +## ⚠️ Dikkat Edilmesi Gerekenler + +1. **UI uygulaması ile aynı auth yapısı kullanılıyor** - Aynı token'lar ve endpoint'ler +2. Blog ve Forum API endpoint'leri henüz backend'de implement edilmemiş olabilir +3. CORS ayarlarının yapılması gerekebilir (Company domain'i için) +4. Production için environment değişkenlerinin güncellenmesi gerekir +5. Error handling mekanizmaları geliştirilmeli +6. Multi-tenancy desteği aktif - Tenant header'ı otomatik ekleniyor + +## 🚧 Yapılacaklar + +- [ ] Backend API endpoint'lerinin implement edilmesi +- [ ] Profil sayfası oluşturulması +- [ ] Forum moderasyon paneli +- [ ] Blog admin paneli +- [ ] Bildirim sistemi +- [ ] Real-time özellikler (WebSocket) +- [ ] Dosya yükleme sistemi +- [ ] Gelişmiş arama özellikleri diff --git a/company/package-lock.json b/company/package-lock.json index 4af767ad..523323e7 100644 --- a/company/package-lock.json +++ b/company/package-lock.json @@ -8,14 +8,21 @@ "name": "sozsoft", "version": "1.0.0", "dependencies": { + "@tanstack/react-query": "^5.17.9", + "axios": "^1.6.5", + "date-fns": "^3.6.0", "glob": "^10.4.5", "lucide-react": "^0.344.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.48.2", + "react-hot-toast": "^2.4.1", + "react-markdown": "^9.0.1", "react-router-dom": "^6.22.2", "react-slick": "^0.30.3", "rimraf": "^4.4.1", - "slick-carousel": "^1.8.1" + "slick-carousel": "^1.8.1", + "zustand": "^4.4.7" }, "devDependencies": { "@types/react": "^18.2.55", @@ -2509,6 +2516,32 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/@tanstack/query-core": { + "version": "5.80.10", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.80.10.tgz", + "integrity": "sha512-mUNQOtzxkjL6jLbyChZoSBP6A5gQDVRUiPvW+/zw/9ftOAz+H754zCj3D8PwnzPKyHzGkQ9JbH48ukhym9LK1Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.80.10", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.80.10.tgz", + "integrity": "sha512-6zM098J8sLy9oU60XAdzUlAH4wVzoMVsWUWiiE/Iz4fd67PplxeyL4sw/MPcVJJVhbwGGXCsHn9GrQt2mlAzig==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.80.10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2550,11 +2583,37 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } }, "node_modules/@types/jquery": { "version": "3.5.32", @@ -2573,17 +2632,30 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" }, "node_modules/@types/react": { "version": "18.3.11", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", - "dev": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2636,6 +2708,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", @@ -2995,7 +3073,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, "license": "ISC" }, "node_modules/@vitejs/plugin-react": { @@ -3181,6 +3258,12 @@ "node": ">= 0.4" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -3244,6 +3327,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", @@ -3286,6 +3380,16 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3389,7 +3493,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -3456,6 +3559,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3473,6 +3586,46 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -3533,6 +3686,28 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -3618,8 +3793,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/data-view-buffer": { "version": "1.0.2", @@ -3675,11 +3849,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3693,6 +3876,19 @@ } } }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3745,6 +3941,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -3787,7 +4014,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -3907,7 +4133,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3917,7 +4142,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3934,7 +4158,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -3947,7 +4170,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4221,6 +4443,16 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -4238,6 +4470,12 @@ "node": ">=0.10.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4447,6 +4685,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -4478,6 +4736,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -4531,7 +4805,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4580,7 +4853,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -4612,7 +4884,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -4748,11 +5019,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.16.tgz", + "integrity": "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4830,7 +5109,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4843,7 +5121,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -4859,7 +5136,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -4867,6 +5143,56 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", @@ -4928,6 +5254,12 @@ "dev": true, "license": "ISC" }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "license": "MIT" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -4943,6 +5275,30 @@ "node": ">= 0.4" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -5089,6 +5445,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5153,6 +5519,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -5219,6 +5595,18 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -5638,6 +6026,16 @@ "dev": true, "license": "MIT" }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -5680,12 +6078,164 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5695,6 +6245,448 @@ "node": ">= 8" } }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -5708,6 +6700,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5732,8 +6745,7 @@ "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/mz": { "version": "2.7.0", @@ -5950,6 +6962,31 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -6237,6 +7274,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -6300,6 +7353,66 @@ "react": "^18.3.1" } }, + "node_modules/react-hook-form": { + "version": "7.58.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.58.1.tgz", + "integrity": "sha512-Lml/KZYEEFfPhUVgE0RdCVpnC4yhW+PndRhbiTtdvSlQTL8IfVR+iQkBjLIvmmc6+GGoVeM11z37ktKFPAb0FA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-hot-toast": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.5.2.tgz", + "integrity": "sha512-Tun3BbCxzmXXM7C+NI4qiv6lT0uwGh4oAfeJyNOjYUejTsm35mK9iCaYLGv8cBz9L5YxZLx/2ii7zsIwPtPUdw==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-markdown": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.1.0.tgz", + "integrity": "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -6481,6 +7594,39 @@ "regjsparser": "bin/parser" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -6996,6 +8142,16 @@ "dev": true, "license": "MIT" }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/string-convert": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", @@ -7143,6 +8299,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/stringify-object": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", @@ -7215,6 +8385,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -7462,6 +8650,26 @@ "punycode": "^2.1.0" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -7659,6 +8867,25 @@ "node": ">=4" } }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -7672,6 +8899,74 @@ "node": ">=8" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -7734,12 +9029,49 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { "version": "5.4.19", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", @@ -8472,6 +9804,44 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/company/package.json b/company/package.json index c5d40284..6dfbac03 100644 --- a/company/package.json +++ b/company/package.json @@ -14,14 +14,21 @@ "format": "npm run prettier:fix && npm run lint:fix" }, "dependencies": { + "@tanstack/react-query": "^5.17.9", + "axios": "^1.6.5", + "date-fns": "^3.6.0", "glob": "^10.4.5", "lucide-react": "^0.344.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.48.2", + "react-hot-toast": "^2.4.1", + "react-markdown": "^9.0.1", "react-router-dom": "^6.22.2", "react-slick": "^0.30.3", "rimraf": "^4.4.1", - "slick-carousel": "^1.8.1" + "slick-carousel": "^1.8.1", + "zustand": "^4.4.7" }, "devDependencies": { "@types/react": "^18.2.55", diff --git a/company/src/App.tsx b/company/src/App.tsx index 345ea0e4..a0cea046 100644 --- a/company/src/App.tsx +++ b/company/src/App.tsx @@ -1,5 +1,7 @@ -import React from 'react'; -import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; +import React, { useEffect } from 'react'; +import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { Toaster } from 'react-hot-toast'; import Layout from './components/layout/Layout'; import Home from './pages/Home'; import Products from './pages/Products'; @@ -8,27 +10,110 @@ import About from './pages/About'; import Blog from './pages/Blog'; import Contact from './pages/Contact'; import BlogDetail from './pages/BlogDetail'; -import NotFound from './pages/NotFound'; // 404 bileşenini import et +import LoginWithTenant from './pages/LoginWithTenant'; +import Register from './pages/Register'; +import Forum from './pages/Forum'; +import ForumCategory from './pages/ForumCategory'; +import Profile from './pages/Profile'; +import NotFound from './pages/NotFound'; import { LanguageProvider } from './context/LanguageContext'; +import { useAuthStore } from './store/authStore'; + +// Create a client +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60 * 5, // 5 minutes + retry: 1, + }, + }, +}); + +// Protected Route Component +const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const { isAuthenticated } = useAuthStore(); + + if (!isAuthenticated) { + return ; + } + + return <>{children}; +}; function App() { + const { checkAuth } = useAuthStore(); + + useEffect(() => { + checkAuth(); + }, [checkAuth]); + return ( - - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - - + + + + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + {/* Protected Routes */} + + + + } /> + + {/* Forum Routes */} + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + + + } /> + + } /> + + + + + + ); } diff --git a/company/src/components/layout/Header.tsx b/company/src/components/layout/Header.tsx index 7c88daba..1a00f224 100644 --- a/company/src/components/layout/Header.tsx +++ b/company/src/components/layout/Header.tsx @@ -1,13 +1,16 @@ import React, { useState, useEffect } from "react"; -import { Menu, X, Globe } from "lucide-react"; +import { Menu, X, Globe, LogIn, LogOut, User, MessageSquare, Home, Info, Package, Briefcase, BookOpen, Phone } from "lucide-react"; import Logo from "./Logo"; -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import { useLanguage } from "../../context/LanguageContext"; +import { useAuthStore } from "../../store/authStore"; const Header: React.FC = () => { const [isOpen, setIsOpen] = useState(false); const [scrolled, setScrolled] = useState(false); const { language, setLanguage, t } = useLanguage(); + const { isAuthenticated, user, logout } = useAuthStore(); + const navigate = useNavigate(); useEffect(() => { const handleScroll = () => { @@ -24,14 +27,19 @@ const Header: React.FC = () => { const toggleMenu = () => setIsOpen(!isOpen); const toggleLanguage = () => setLanguage(language === "en" ? "tr" : "en"); + const handleLogout = () => { + logout(); + navigate('/'); + }; + const navLinks = [ - { name: t("nav.home"), path: "/" }, - { name: t("nav.about"), path: "/about" }, - { name: t("nav.products"), path: "/products" }, - { name: t("nav.services"), path: "/services" }, - { name: t("nav.blog"), path: "/blog" }, - { name: t("nav.contact"), path: "/contact" }, - { name: t("nav.demo"), path: import.meta.env.VITE_KURS_URL }, + { name: t("nav.home"), path: "/", icon: Home }, + { name: t("nav.about"), path: "/about", icon: Info }, + { name: t("nav.products"), path: "/products", icon: Package }, + { name: t("nav.services"), path: "/services", icon: Briefcase }, + { name: t("nav.blog"), path: "/blog", icon: BookOpen }, + { name: t("nav.forum") || "Forum", path: "/forum", icon: MessageSquare, protected: true }, + { name: t("nav.contact"), path: "/contact", icon: Phone }, ]; return ( @@ -48,18 +56,21 @@ const Header: React.FC = () => { {/* Desktop Navigation */} -