Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions src/Analysim.Core/Entities/Notification.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Core.Entities
{
public class Notification
{
[Key]
public int NotificationID { get; set; }

[ForeignKey("RecipientUser")]
public int RecipientUserID { get; set; }
public User RecipientUser { get; set; }

[ForeignKey("ActorUser")]
public int? ActorUserID { get; set; }
public User ActorUser { get; set; }

[Required]
[MaxLength(100)]
public string Type { get; set; }

[ForeignKey("Project")]
public int? ProjectID { get; set; }
public Project Project { get; set; }

[ForeignKey("ProjectComment")]
public int? CommentID { get; set; }
public ProjectComment ProjectComment { get; set; }

[ForeignKey("ProjectLog")]
public int? ProjectLogID { get; set; }
public ProjectLog ProjectLog { get; set; }

[Required]
[MaxLength(200)]
public string Title { get; set; }

[Required]
[MaxLength(1000)]
public string Body { get; set; }

[MaxLength(500)]
public string Link { get; set; }

public string DataJson { get; set; }

public bool IsRead { get; set; }

public DateTime? ReadAt { get; set; }

public DateTime CreatedAt { get; set; }
}
}
20 changes: 20 additions & 0 deletions src/Analysim.Core/Entities/UserNotificationPreference.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Core.Entities
{
public class UserNotificationPreference
{
[ForeignKey("User")]
public int UserID { get; set; }
public User User { get; set; }

[Required]
[MaxLength(100)]
public string NotificationType { get; set; }

public bool InAppEnabled { get; set; } = true;

public bool EmailEnabled { get; set; }
}
}
11 changes: 11 additions & 0 deletions src/Analysim.Core/Helper/NotificationTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Core.Helper
{
public static class NotificationTypes
{
public const string CommentReply = "comment.reply";
public const string ProjectMemberAdded = "project.member.added";
public const string ProjectJoined = "project.joined";
public const string ProjectLogCreated = "project.log.created";
public const string ProjectLogUpdated = "project.log.updated";
}
}
10 changes: 10 additions & 0 deletions src/Analysim.Core/Interfaces/INotificationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Core.Models;

namespace Core.Interfaces
{
public interface INotificationService
{
Task PublishAsync(NotificationEvent notificationEvent);
}
}
16 changes: 16 additions & 0 deletions src/Analysim.Core/Models/NotificationEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;

namespace Core.Models
{
public class NotificationEvent
{
public string Type { get; set; }
public int? ActorUserID { get; set; }
public int? RecipientUserID { get; set; }
public int? ProjectID { get; set; }
public int? CommentID { get; set; }
public int? ParentCommentID { get; set; }
public int? ProjectLogID { get; set; }
public IDictionary<string, string> Data { get; set; } = new Dictionary<string, string>();
}
}
52 changes: 52 additions & 0 deletions src/Analysim.Infrastructure/Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<ProjectTag>().HasKey(pt => new { pt.ProjectID, pt.TagID });
modelBuilder.Entity<UserUser>().HasKey(uu => new { uu.UserID, uu.FollowerID });
modelBuilder.Entity<NotebookContent>().HasKey(nc => new { nc.NotebookID, nc.Version });
modelBuilder.Entity<UserNotificationPreference>().HasKey(p => new { p.UserID, p.NotificationType });

modelBuilder.Entity<RefreshToken>()
.HasIndex(rt => rt.TokenHash)
Expand Down Expand Up @@ -84,6 +85,55 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.HasForeignKey(rt => rt.UserID)
.OnDelete(DeleteBehavior.Cascade);

#region Notifications

modelBuilder.Entity<Notification>()
.HasOne(n => n.RecipientUser)
.WithMany()
.HasForeignKey(n => n.RecipientUserID)
.OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<Notification>()
.HasOne(n => n.ActorUser)
.WithMany()
.HasForeignKey(n => n.ActorUserID)
.OnDelete(DeleteBehavior.SetNull);

modelBuilder.Entity<Notification>()
.HasOne(n => n.Project)
.WithMany()
.HasForeignKey(n => n.ProjectID)
.OnDelete(DeleteBehavior.SetNull);

modelBuilder.Entity<Notification>()
.HasOne(n => n.ProjectComment)
.WithMany()
.HasForeignKey(n => n.CommentID)
.OnDelete(DeleteBehavior.SetNull);

modelBuilder.Entity<Notification>()
.HasOne(n => n.ProjectLog)
.WithMany()
.HasForeignKey(n => n.ProjectLogID)
.OnDelete(DeleteBehavior.SetNull);

modelBuilder.Entity<UserNotificationPreference>()
.HasOne(p => p.User)
.WithMany()
.HasForeignKey(p => p.UserID)
.OnDelete(DeleteBehavior.Cascade);

modelBuilder.Entity<Notification>()
.HasIndex(n => new { n.RecipientUserID, n.IsRead, n.CreatedAt });

modelBuilder.Entity<Notification>()
.HasIndex(n => n.Type);

modelBuilder.Entity<UserNotificationPreference>()
.HasIndex(p => p.NotificationType);

#endregion

// One To Many Relationship (Project -> Blob)
modelBuilder.Entity<Project>()
.HasMany(p => p.BlobFiles)
Expand Down Expand Up @@ -279,5 +329,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
public DbSet<ProjectLog> ProjectLogs { get; set; }

public DbSet<Publication> Publications { get; set; }
public DbSet<Notification> Notifications { get; set; }
public DbSet<UserNotificationPreference> UserNotificationPreferences { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,77 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("Notebook");
});

modelBuilder.Entity("Core.Entities.Notification", b =>
{
b.Property<int>("NotificationID")
.ValueGeneratedOnAdd()
.HasColumnType("integer");

NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("NotificationID"));

b.Property<int?>("ActorUserID")
.HasColumnType("integer");

b.Property<string>("Body")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("character varying(1000)");

b.Property<int?>("CommentID")
.HasColumnType("integer");

b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");

b.Property<string>("DataJson")
.HasColumnType("text");

b.Property<bool>("IsRead")
.HasColumnType("boolean");

b.Property<string>("Link")
.HasMaxLength(500)
.HasColumnType("character varying(500)");

b.Property<int?>("ProjectID")
.HasColumnType("integer");

b.Property<int?>("ProjectLogID")
.HasColumnType("integer");

b.Property<DateTime?>("ReadAt")
.HasColumnType("timestamp with time zone");

b.Property<int>("RecipientUserID")
.HasColumnType("integer");

b.Property<string>("Title")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("character varying(200)");

b.Property<string>("Type")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");

b.HasKey("NotificationID");

b.HasIndex("ActorUserID");

b.HasIndex("CommentID");

b.HasIndex("ProjectID");

b.HasIndex("ProjectLogID");

b.HasIndex("Type");

b.HasIndex("RecipientUserID", "IsRead", "CreatedAt");

b.ToTable("Notifications");
});

modelBuilder.Entity("Core.Entities.ObservableNotebookDataset", b =>
{
b.Property<int>("ID")
Expand Down Expand Up @@ -644,6 +715,28 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("AspNetUsers", (string)null);
});

modelBuilder.Entity("Core.Entities.UserNotificationPreference", b =>
{
b.Property<int>("UserID")
.HasColumnType("integer");

b.Property<string>("NotificationType")
.HasMaxLength(100)
.HasColumnType("character varying(100)");

b.Property<bool>("EmailEnabled")
.HasColumnType("boolean");

b.Property<bool>("InAppEnabled")
.HasColumnType("boolean");

b.HasKey("UserID", "NotificationType");

b.HasIndex("NotificationType");

b.ToTable("UserNotificationPreferences");
});

modelBuilder.Entity("Core.Entities.UserUser", b =>
{
b.Property<int>("UserID")
Expand Down Expand Up @@ -866,6 +959,45 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("Project");
});

modelBuilder.Entity("Core.Entities.Notification", b =>
{
b.HasOne("Core.Entities.User", "ActorUser")
.WithMany()
.HasForeignKey("ActorUserID")
.OnDelete(DeleteBehavior.SetNull);

b.HasOne("Core.Entities.ProjectComment", "ProjectComment")
.WithMany()
.HasForeignKey("CommentID")
.OnDelete(DeleteBehavior.SetNull);

b.HasOne("Core.Entities.Project", "Project")
.WithMany()
.HasForeignKey("ProjectID")
.OnDelete(DeleteBehavior.SetNull);

b.HasOne("Core.Entities.ProjectLog", "ProjectLog")
.WithMany()
.HasForeignKey("ProjectLogID")
.OnDelete(DeleteBehavior.SetNull);

b.HasOne("Core.Entities.User", "RecipientUser")
.WithMany()
.HasForeignKey("RecipientUserID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.Navigation("ActorUser");

b.Navigation("Project");

b.Navigation("ProjectComment");

b.Navigation("ProjectLog");

b.Navigation("RecipientUser");
});

modelBuilder.Entity("Core.Entities.ObservableNotebookDataset", b =>
{
b.HasOne("Core.Entities.Notebook", "notebook")
Expand Down Expand Up @@ -1041,6 +1173,17 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("User");
});

modelBuilder.Entity("Core.Entities.UserNotificationPreference", b =>
{
b.HasOne("Core.Entities.User", "User")
.WithMany()
.HasForeignKey("UserID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.Navigation("User");
});

modelBuilder.Entity("Core.Entities.UserUser", b =>
{
b.HasOne("Core.Entities.User", "Follower")
Expand Down
Loading
Loading