Classroom : Büyük güncellemee
This commit is contained in:
parent
b904b35506
commit
cf3cb50e1a
25 changed files with 2156 additions and 1856 deletions
|
|
@ -2,7 +2,7 @@ using System;
|
||||||
|
|
||||||
namespace Kurs.Platform.Classrooms;
|
namespace Kurs.Platform.Classrooms;
|
||||||
|
|
||||||
public class ClassChatDto
|
public class ClassroomChatDto
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
|
|
@ -10,5 +10,8 @@ public class ClassChatDto
|
||||||
public string SenderName { get; set; }
|
public string SenderName { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public DateTime Timestamp { get; set; }
|
public DateTime Timestamp { get; set; }
|
||||||
|
public Guid? RecipientId { get; set; }
|
||||||
|
public string? RecipientName { get; set; }
|
||||||
public bool IsTeacher { get; set; }
|
public bool IsTeacher { get; set; }
|
||||||
|
public string MessageType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ public class GetClassroomListDto : PagedAndSortedResultRequestDto
|
||||||
public Guid? TeacherId { get; set; }
|
public Guid? TeacherId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ClassAttendanceDto : EntityDto<Guid>
|
public class ClassroomAttendanceDto : EntityDto<Guid>
|
||||||
{
|
{
|
||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
public Guid StudentId { get; set; }
|
public Guid StudentId { get; set; }
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@ using System;
|
||||||
|
|
||||||
namespace Kurs.Platform.Classrooms;
|
namespace Kurs.Platform.Classrooms;
|
||||||
|
|
||||||
public class ClassParticipantDto
|
public class ClassroomParticipantDto
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
public Guid UserId { get; set; }
|
public Guid UserId { get; set; }
|
||||||
public string UserName { get; set; }
|
public string UserName { get; set; }
|
||||||
public string UserEmail { get; set; }
|
|
||||||
public bool IsTeacher { get; set; }
|
public bool IsTeacher { get; set; }
|
||||||
public bool IsAudioMuted { get; set; }
|
public bool IsAudioMuted { get; set; }
|
||||||
public bool IsVideoMuted { get; set; }
|
public bool IsVideoMuted { get; set; }
|
||||||
|
public bool IsHandRaised { get; set; }
|
||||||
public DateTime JoinTime { get; set; }
|
public DateTime JoinTime { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -17,5 +17,5 @@ public interface IClassroomAppService : IApplicationService
|
||||||
Task EndClassAsync(Guid id);
|
Task EndClassAsync(Guid id);
|
||||||
Task<ClassroomDto> JoinClassAsync(Guid id);
|
Task<ClassroomDto> JoinClassAsync(Guid id);
|
||||||
Task LeaveClassAsync(Guid id);
|
Task LeaveClassAsync(Guid id);
|
||||||
Task<List<ClassAttendanceDto>> GetAttendanceAsync(Guid sessionId);
|
Task<List<ClassroomAttendanceDto>> GetAttendanceAsync(Guid sessionId);
|
||||||
}
|
}
|
||||||
|
|
@ -15,13 +15,13 @@ namespace Kurs.Platform.Classrooms;
|
||||||
public class ClassroomAppService : PlatformAppService, IClassroomAppService
|
public class ClassroomAppService : PlatformAppService, IClassroomAppService
|
||||||
{
|
{
|
||||||
private readonly IRepository<Classroom, Guid> _classSessionRepository;
|
private readonly IRepository<Classroom, Guid> _classSessionRepository;
|
||||||
private readonly IRepository<ClassParticipant, Guid> _participantRepository;
|
private readonly IRepository<ClassroomParticipant, Guid> _participantRepository;
|
||||||
private readonly IRepository<ClassAttandance, Guid> _attendanceRepository;
|
private readonly IRepository<ClassroomAttandance, Guid> _attendanceRepository;
|
||||||
|
|
||||||
public ClassroomAppService(
|
public ClassroomAppService(
|
||||||
IRepository<Classroom, Guid> classSessionRepository,
|
IRepository<Classroom, Guid> classSessionRepository,
|
||||||
IRepository<ClassParticipant, Guid> participantRepository,
|
IRepository<ClassroomParticipant, Guid> participantRepository,
|
||||||
IRepository<ClassAttandance, Guid> attendanceRepository)
|
IRepository<ClassroomAttandance, Guid> attendanceRepository)
|
||||||
{
|
{
|
||||||
_classSessionRepository = classSessionRepository;
|
_classSessionRepository = classSessionRepository;
|
||||||
_participantRepository = participantRepository;
|
_participantRepository = participantRepository;
|
||||||
|
|
@ -198,19 +198,18 @@ public class ClassroomAppService : PlatformAppService, IClassroomAppService
|
||||||
if (existingParticipant == null)
|
if (existingParticipant == null)
|
||||||
{
|
{
|
||||||
// Add participant
|
// Add participant
|
||||||
var participant = new ClassParticipant(
|
var participant = new ClassroomParticipant(
|
||||||
GuidGenerator.Create(),
|
GuidGenerator.Create(),
|
||||||
id,
|
id,
|
||||||
CurrentUser.Id,
|
CurrentUser.Id,
|
||||||
CurrentUser.Name,
|
CurrentUser.Name,
|
||||||
CurrentUser.Email,
|
|
||||||
false // isTeacher
|
false // isTeacher
|
||||||
);
|
);
|
||||||
|
|
||||||
await _participantRepository.InsertAsync(participant);
|
await _participantRepository.InsertAsync(participant);
|
||||||
|
|
||||||
// Create attendance record
|
// Create attendance record
|
||||||
var attendance = new ClassAttandance(
|
var attendance = new ClassroomAttandance(
|
||||||
GuidGenerator.Create(),
|
GuidGenerator.Create(),
|
||||||
id,
|
id,
|
||||||
CurrentUser.Id,
|
CurrentUser.Id,
|
||||||
|
|
@ -257,7 +256,7 @@ public class ClassroomAppService : PlatformAppService, IClassroomAppService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<ClassAttendanceDto>> GetAttendanceAsync(Guid sessionId)
|
public async Task<List<ClassroomAttendanceDto>> GetAttendanceAsync(Guid sessionId)
|
||||||
{
|
{
|
||||||
var classSession = await _classSessionRepository.GetAsync(sessionId);
|
var classSession = await _classSessionRepository.GetAsync(sessionId);
|
||||||
|
|
||||||
|
|
@ -270,6 +269,6 @@ public class ClassroomAppService : PlatformAppService, IClassroomAppService
|
||||||
x => x.SessionId == sessionId
|
x => x.SessionId == sessionId
|
||||||
);
|
);
|
||||||
|
|
||||||
return ObjectMapper.Map<List<ClassAttandance>, List<ClassAttendanceDto>>(attendanceRecords);
|
return ObjectMapper.Map<List<ClassroomAttandance>, List<ClassroomAttendanceDto>>(attendanceRecords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +8,8 @@ public class ClassroomAutoMapperProfile : Profile
|
||||||
public ClassroomAutoMapperProfile()
|
public ClassroomAutoMapperProfile()
|
||||||
{
|
{
|
||||||
CreateMap<Classroom, ClassroomDto>();
|
CreateMap<Classroom, ClassroomDto>();
|
||||||
CreateMap<ClassAttandance, ClassAttendanceDto>();
|
CreateMap<ClassroomAttandance, ClassroomAttendanceDto>();
|
||||||
CreateMap<ClassParticipant, ClassParticipantDto>();
|
CreateMap<ClassroomParticipant, ClassroomParticipantDto>();
|
||||||
CreateMap<ClassChat, ClassChatDto>();
|
CreateMap<ClassroomChat, ClassroomChatDto>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,15 @@ public class Classroom : FullAuditedEntity<Guid>
|
||||||
public int ParticipantCount { get; set; }
|
public int ParticipantCount { get; set; }
|
||||||
public string SettingsJson { get; set; }
|
public string SettingsJson { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<ClassParticipant> Participants { get; set; }
|
public virtual ICollection<ClassroomParticipant> Participants { get; set; }
|
||||||
public virtual ICollection<ClassAttandance> AttendanceRecords { get; set; }
|
public virtual ICollection<ClassroomAttandance> AttendanceRecords { get; set; }
|
||||||
public virtual ICollection<ClassChat> ChatMessages { get; set; }
|
public virtual ICollection<ClassroomChat> ChatMessages { get; set; }
|
||||||
|
|
||||||
protected Classroom()
|
protected Classroom()
|
||||||
{
|
{
|
||||||
Participants = new HashSet<ClassParticipant>();
|
Participants = new HashSet<ClassroomParticipant>();
|
||||||
AttendanceRecords = new HashSet<ClassAttandance>();
|
AttendanceRecords = new HashSet<ClassroomAttandance>();
|
||||||
ChatMessages = new HashSet<ClassChat>();
|
ChatMessages = new HashSet<ClassroomChat>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Classroom(
|
public Classroom(
|
||||||
|
|
@ -56,8 +56,8 @@ public class Classroom : FullAuditedEntity<Guid>
|
||||||
MaxParticipants = maxParticipants;
|
MaxParticipants = maxParticipants;
|
||||||
SettingsJson = settingsJson;
|
SettingsJson = settingsJson;
|
||||||
|
|
||||||
Participants = new HashSet<ClassParticipant>();
|
Participants = new HashSet<ClassroomParticipant>();
|
||||||
AttendanceRecords = new HashSet<ClassAttandance>();
|
AttendanceRecords = new HashSet<ClassroomAttandance>();
|
||||||
ChatMessages = new HashSet<ClassChat>();
|
ChatMessages = new HashSet<ClassroomChat>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
||||||
public class ClassAttandance : FullAuditedEntity<Guid>
|
public class ClassroomAttandance : FullAuditedEntity<Guid>
|
||||||
{
|
{
|
||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
public Guid? StudentId { get; set; }
|
public Guid? StudentId { get; set; }
|
||||||
|
|
@ -15,11 +15,11 @@ public class ClassAttandance : FullAuditedEntity<Guid>
|
||||||
// Navigation properties
|
// Navigation properties
|
||||||
public virtual Classroom Session { get; set; }
|
public virtual Classroom Session { get; set; }
|
||||||
|
|
||||||
protected ClassAttandance()
|
protected ClassroomAttandance()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassAttandance(
|
public ClassroomAttandance(
|
||||||
Guid id,
|
Guid id,
|
||||||
Guid sessionId,
|
Guid sessionId,
|
||||||
Guid? studentId,
|
Guid? studentId,
|
||||||
|
|
@ -3,36 +3,45 @@ using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
||||||
public class ClassChat : FullAuditedEntity<Guid>
|
public class ClassroomChat : FullAuditedEntity<Guid>
|
||||||
{
|
{
|
||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
public Guid? SenderId { get; set; }
|
public Guid? SenderId { get; set; }
|
||||||
public string SenderName { get; set; }
|
public string SenderName { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public DateTime Timestamp { get; set; }
|
public DateTime Timestamp { get; set; }
|
||||||
|
public Guid? RecipientId { get; set; }
|
||||||
|
public string? RecipientName { get; set; }
|
||||||
public bool IsTeacher { get; set; }
|
public bool IsTeacher { get; set; }
|
||||||
|
public string MessageType { get; set; }
|
||||||
|
|
||||||
// Navigation properties
|
// Navigation properties
|
||||||
public virtual Classroom Session { get; set; }
|
public virtual Classroom Session { get; set; }
|
||||||
|
|
||||||
protected ClassChat()
|
protected ClassroomChat()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassChat(
|
public ClassroomChat(
|
||||||
Guid id,
|
Guid id,
|
||||||
Guid sessionId,
|
Guid sessionId,
|
||||||
Guid? senderId,
|
Guid? senderId,
|
||||||
string senderName,
|
string senderName,
|
||||||
string message,
|
string message,
|
||||||
bool isTeacher
|
Guid? recipientId,
|
||||||
|
string recipientName,
|
||||||
|
bool isTeacher,
|
||||||
|
string messageType
|
||||||
) : base(id)
|
) : base(id)
|
||||||
{
|
{
|
||||||
SessionId = sessionId;
|
SessionId = sessionId;
|
||||||
SenderId = senderId;
|
SenderId = senderId;
|
||||||
SenderName = senderName;
|
SenderName = senderName;
|
||||||
Message = message;
|
Message = message;
|
||||||
|
RecipientId = recipientId;
|
||||||
|
RecipientName = recipientName;
|
||||||
IsTeacher = isTeacher;
|
IsTeacher = isTeacher;
|
||||||
Timestamp = DateTime.UtcNow;
|
Timestamp = DateTime.UtcNow;
|
||||||
|
MessageType = messageType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,41 +3,40 @@ using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
|
||||||
namespace Kurs.Platform.Entities;
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
||||||
public class ClassParticipant : FullAuditedEntity<Guid>
|
public class ClassroomParticipant : FullAuditedEntity<Guid>
|
||||||
{
|
{
|
||||||
public Guid SessionId { get; set; }
|
public Guid SessionId { get; set; }
|
||||||
public Guid? UserId { get; set; }
|
public Guid? UserId { get; set; }
|
||||||
public string UserName { get; set; }
|
public string UserName { get; set; }
|
||||||
public string UserEmail { get; set; }
|
|
||||||
public bool IsTeacher { get; set; }
|
public bool IsTeacher { get; set; }
|
||||||
public bool IsAudioMuted { get; set; }
|
public bool IsAudioMuted { get; set; } = false;
|
||||||
public bool IsVideoMuted { get; set; }
|
public bool IsVideoMuted { get; set; } = false;
|
||||||
|
public bool IsHandRaised { get; set; } = false;
|
||||||
public DateTime JoinTime { get; set; }
|
public DateTime JoinTime { get; set; }
|
||||||
public string ConnectionId { get; set; }
|
public string ConnectionId { get; set; }
|
||||||
|
|
||||||
// Navigation properties
|
// Navigation properties
|
||||||
public virtual Classroom Session { get; set; }
|
public virtual Classroom Session { get; set; }
|
||||||
|
|
||||||
protected ClassParticipant()
|
protected ClassroomParticipant()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassParticipant(
|
public ClassroomParticipant(
|
||||||
Guid id,
|
Guid id,
|
||||||
Guid sessionId,
|
Guid sessionId,
|
||||||
Guid? userId,
|
Guid? userId,
|
||||||
string userName,
|
string userName,
|
||||||
string userEmail,
|
|
||||||
bool isTeacher
|
bool isTeacher
|
||||||
) : base(id)
|
) : base(id)
|
||||||
{
|
{
|
||||||
SessionId = sessionId;
|
SessionId = sessionId;
|
||||||
UserId = userId;
|
UserId = userId;
|
||||||
UserName = userName;
|
UserName = userName;
|
||||||
UserEmail = userEmail;
|
|
||||||
IsTeacher = isTeacher;
|
IsTeacher = isTeacher;
|
||||||
IsAudioMuted = false;
|
IsAudioMuted = false;
|
||||||
IsVideoMuted = false;
|
IsVideoMuted = false;
|
||||||
|
IsHandRaised = false;
|
||||||
JoinTime = DateTime.UtcNow;
|
JoinTime = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,9 +98,9 @@ public class PlatformDbContext :
|
||||||
public DbSet<Service> Services { get; set; }
|
public DbSet<Service> Services { get; set; }
|
||||||
|
|
||||||
public DbSet<Classroom> ClassSessions { get; set; }
|
public DbSet<Classroom> ClassSessions { get; set; }
|
||||||
public DbSet<ClassParticipant> Participants { get; set; }
|
public DbSet<ClassroomParticipant> Participants { get; set; }
|
||||||
public DbSet<ClassAttandance> AttendanceRecords { get; set; }
|
public DbSet<ClassroomAttandance> AttendanceRecords { get; set; }
|
||||||
public DbSet<ClassChat> ChatMessages { get; set; }
|
public DbSet<ClassroomChat> ChatMessages { get; set; }
|
||||||
|
|
||||||
#region Entities from the modules
|
#region Entities from the modules
|
||||||
|
|
||||||
|
|
@ -913,13 +913,12 @@ public class PlatformDbContext :
|
||||||
});
|
});
|
||||||
|
|
||||||
// Participant
|
// Participant
|
||||||
builder.Entity<ClassParticipant>(b =>
|
builder.Entity<ClassroomParticipant>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(PlatformConsts.DbTablePrefix + nameof(ClassParticipant), PlatformConsts.DbSchema);
|
b.ToTable(PlatformConsts.DbTablePrefix + nameof(ClassroomParticipant), PlatformConsts.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.UserName).IsRequired().HasMaxLength(100);
|
b.Property(x => x.UserName).IsRequired().HasMaxLength(100);
|
||||||
b.Property(x => x.UserEmail).HasMaxLength(200);
|
|
||||||
b.Property(x => x.ConnectionId).HasMaxLength(100);
|
b.Property(x => x.ConnectionId).HasMaxLength(100);
|
||||||
|
|
||||||
b.HasIndex(x => x.SessionId);
|
b.HasIndex(x => x.SessionId);
|
||||||
|
|
@ -928,9 +927,9 @@ public class PlatformDbContext :
|
||||||
});
|
});
|
||||||
|
|
||||||
// AttendanceRecord
|
// AttendanceRecord
|
||||||
builder.Entity<ClassAttandance>(b =>
|
builder.Entity<ClassroomAttandance>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(PlatformConsts.DbTablePrefix + nameof(ClassAttandance), PlatformConsts.DbSchema);
|
b.ToTable(PlatformConsts.DbTablePrefix + nameof(ClassroomAttandance), PlatformConsts.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.StudentName).IsRequired().HasMaxLength(100);
|
b.Property(x => x.StudentName).IsRequired().HasMaxLength(100);
|
||||||
|
|
@ -941,9 +940,9 @@ public class PlatformDbContext :
|
||||||
});
|
});
|
||||||
|
|
||||||
// ChatMessage
|
// ChatMessage
|
||||||
builder.Entity<ClassChat>(b =>
|
builder.Entity<ClassroomChat>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(PlatformConsts.DbTablePrefix + nameof(ClassChat), PlatformConsts.DbSchema);
|
b.ToTable(PlatformConsts.DbTablePrefix + nameof(ClassroomChat), PlatformConsts.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.SenderName).IsRequired().HasMaxLength(100);
|
b.Property(x => x.SenderName).IsRequired().HasMaxLength(100);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Kurs.Platform.Migrations
|
namespace Kurs.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20250828112303_Initial")]
|
[Migration("20250829093104_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -1559,219 +1559,6 @@ namespace Kurs.Platform.Migrations
|
||||||
b.ToTable("PCity", (string)null);
|
b.ToTable("PCity", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassAttandance", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<DateTime>("JoinTime")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LeaveTime")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<Guid>("SessionId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<Guid?>("StudentId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("StudentName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.Property<int>("TotalDurationMinutes")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("JoinTime");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId");
|
|
||||||
|
|
||||||
b.HasIndex("StudentId");
|
|
||||||
|
|
||||||
b.ToTable("PClassAttandance", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassChat", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsTeacher")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Message")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("nvarchar(2000)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("SenderId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("SenderName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.Property<Guid>("SessionId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<DateTime>("Timestamp")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("SenderId");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId");
|
|
||||||
|
|
||||||
b.HasIndex("Timestamp");
|
|
||||||
|
|
||||||
b.ToTable("PClassChat", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassParticipant", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("ConnectionId")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAudioMuted")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsTeacher")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<bool>("IsVideoMuted")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime>("JoinTime")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<Guid>("SessionId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("UserEmail")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("UserId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId", "UserId")
|
|
||||||
.IsUnique()
|
|
||||||
.HasFilter("[UserId] IS NOT NULL");
|
|
||||||
|
|
||||||
b.ToTable("PClassParticipant", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Classroom", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Classroom", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -1861,6 +1648,227 @@ namespace Kurs.Platform.Migrations
|
||||||
b.ToTable("PClassroom", (string)null);
|
b.ToTable("PClassroom", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LeaveTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<Guid>("SessionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<Guid?>("StudentId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("StudentName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<int>("TotalDurationMinutes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("JoinTime");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId");
|
||||||
|
|
||||||
|
b.HasIndex("StudentId");
|
||||||
|
|
||||||
|
b.ToTable("PClassroomAttandance", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("IsTeacher")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000)
|
||||||
|
.HasColumnType("nvarchar(2000)");
|
||||||
|
|
||||||
|
b.Property<string>("MessageType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("RecipientId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("SenderId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("SenderName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<Guid>("SessionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Timestamp")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId");
|
||||||
|
|
||||||
|
b.HasIndex("Timestamp");
|
||||||
|
|
||||||
|
b.ToTable("PClassroomChat", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("ConnectionId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAudioMuted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("IsHandRaised")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsTeacher")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsVideoMuted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<Guid>("SessionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UserId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId", "UserId")
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[UserId] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("PClassroomParticipant", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -6558,7 +6566,7 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Country");
|
b.Navigation("Country");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassAttandance", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
||||||
.WithMany("AttendanceRecords")
|
.WithMany("AttendanceRecords")
|
||||||
|
|
@ -6569,7 +6577,7 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Session");
|
b.Navigation("Session");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassChat", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
||||||
.WithMany("ChatMessages")
|
.WithMany("ChatMessages")
|
||||||
|
|
@ -6580,7 +6588,7 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Session");
|
b.Navigation("Session");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassParticipant", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
||||||
.WithMany("Participants")
|
.WithMany("Participants")
|
||||||
|
|
@ -1922,7 +1922,7 @@ namespace Kurs.Platform.Migrations
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "PClassAttandance",
|
name: "PClassroomAttandance",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
|
@ -1942,9 +1942,9 @@ namespace Kurs.Platform.Migrations
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_PClassAttandance", x => x.Id);
|
table.PrimaryKey("PK_PClassroomAttandance", x => x.Id);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_PClassAttandance_PClassroom_SessionId",
|
name: "FK_PClassroomAttandance_PClassroom_SessionId",
|
||||||
column: x => x.SessionId,
|
column: x => x.SessionId,
|
||||||
principalTable: "PClassroom",
|
principalTable: "PClassroom",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
|
|
@ -1952,7 +1952,7 @@ namespace Kurs.Platform.Migrations
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "PClassChat",
|
name: "PClassroomChat",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
|
@ -1961,7 +1961,10 @@ namespace Kurs.Platform.Migrations
|
||||||
SenderName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
SenderName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
Message = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
|
Message = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
|
||||||
Timestamp = table.Column<DateTime>(type: "datetime2", nullable: false),
|
Timestamp = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
RecipientId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
RecipientName = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
IsTeacher = table.Column<bool>(type: "bit", nullable: false),
|
IsTeacher = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
MessageType = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
|
@ -1972,9 +1975,9 @@ namespace Kurs.Platform.Migrations
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_PClassChat", x => x.Id);
|
table.PrimaryKey("PK_PClassroomChat", x => x.Id);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_PClassChat_PClassroom_SessionId",
|
name: "FK_PClassroomChat_PClassroom_SessionId",
|
||||||
column: x => x.SessionId,
|
column: x => x.SessionId,
|
||||||
principalTable: "PClassroom",
|
principalTable: "PClassroom",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
|
|
@ -1982,17 +1985,17 @@ namespace Kurs.Platform.Migrations
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "PClassParticipant",
|
name: "PClassroomParticipant",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
UserName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
UserName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
UserEmail = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
|
|
||||||
IsTeacher = table.Column<bool>(type: "bit", nullable: false),
|
IsTeacher = table.Column<bool>(type: "bit", nullable: false),
|
||||||
IsAudioMuted = table.Column<bool>(type: "bit", nullable: false),
|
IsAudioMuted = table.Column<bool>(type: "bit", nullable: false),
|
||||||
IsVideoMuted = table.Column<bool>(type: "bit", nullable: false),
|
IsVideoMuted = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsHandRaised = table.Column<bool>(type: "bit", nullable: false),
|
||||||
JoinTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
JoinTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
ConnectionId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
ConnectionId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
|
@ -2005,9 +2008,9 @@ namespace Kurs.Platform.Migrations
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_PClassParticipant", x => x.Id);
|
table.PrimaryKey("PK_PClassroomParticipant", x => x.Id);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_PClassParticipant_PClassroom_SessionId",
|
name: "FK_PClassroomParticipant_PClassroom_SessionId",
|
||||||
column: x => x.SessionId,
|
column: x => x.SessionId,
|
||||||
principalTable: "PClassroom",
|
principalTable: "PClassroom",
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
|
|
@ -2991,53 +2994,6 @@ namespace Kurs.Platform.Migrations
|
||||||
columns: new[] { "CountryCode", "Code" },
|
columns: new[] { "CountryCode", "Code" },
|
||||||
unique: true);
|
unique: true);
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassAttandance_JoinTime",
|
|
||||||
table: "PClassAttandance",
|
|
||||||
column: "JoinTime");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassAttandance_SessionId",
|
|
||||||
table: "PClassAttandance",
|
|
||||||
column: "SessionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassAttandance_StudentId",
|
|
||||||
table: "PClassAttandance",
|
|
||||||
column: "StudentId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassChat_SenderId",
|
|
||||||
table: "PClassChat",
|
|
||||||
column: "SenderId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassChat_SessionId",
|
|
||||||
table: "PClassChat",
|
|
||||||
column: "SessionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassChat_Timestamp",
|
|
||||||
table: "PClassChat",
|
|
||||||
column: "Timestamp");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassParticipant_SessionId",
|
|
||||||
table: "PClassParticipant",
|
|
||||||
column: "SessionId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassParticipant_SessionId_UserId",
|
|
||||||
table: "PClassParticipant",
|
|
||||||
columns: new[] { "SessionId", "UserId" },
|
|
||||||
unique: true,
|
|
||||||
filter: "[UserId] IS NOT NULL");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassParticipant_UserId",
|
|
||||||
table: "PClassParticipant",
|
|
||||||
column: "UserId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_PClassroom_ScheduledStartTime",
|
name: "IX_PClassroom_ScheduledStartTime",
|
||||||
table: "PClassroom",
|
table: "PClassroom",
|
||||||
|
|
@ -3048,6 +3004,53 @@ namespace Kurs.Platform.Migrations
|
||||||
table: "PClassroom",
|
table: "PClassroom",
|
||||||
column: "TeacherId");
|
column: "TeacherId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomAttandance_JoinTime",
|
||||||
|
table: "PClassroomAttandance",
|
||||||
|
column: "JoinTime");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomAttandance_SessionId",
|
||||||
|
table: "PClassroomAttandance",
|
||||||
|
column: "SessionId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomAttandance_StudentId",
|
||||||
|
table: "PClassroomAttandance",
|
||||||
|
column: "StudentId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomChat_SenderId",
|
||||||
|
table: "PClassroomChat",
|
||||||
|
column: "SenderId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomChat_SessionId",
|
||||||
|
table: "PClassroomChat",
|
||||||
|
column: "SessionId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomChat_Timestamp",
|
||||||
|
table: "PClassroomChat",
|
||||||
|
column: "Timestamp");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomParticipant_SessionId",
|
||||||
|
table: "PClassroomParticipant",
|
||||||
|
column: "SessionId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomParticipant_SessionId_UserId",
|
||||||
|
table: "PClassroomParticipant",
|
||||||
|
columns: new[] { "SessionId", "UserId" },
|
||||||
|
unique: true,
|
||||||
|
filter: "[UserId] IS NOT NULL");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_PClassroomParticipant_UserId",
|
||||||
|
table: "PClassroomParticipant",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_PCountry_Code",
|
name: "IX_PCountry_Code",
|
||||||
table: "PCountry",
|
table: "PCountry",
|
||||||
|
|
@ -3303,13 +3306,13 @@ namespace Kurs.Platform.Migrations
|
||||||
name: "PChart");
|
name: "PChart");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PClassAttandance");
|
name: "PClassroomAttandance");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PClassChat");
|
name: "PClassroomChat");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PClassParticipant");
|
name: "PClassroomParticipant");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PContact");
|
name: "PContact");
|
||||||
|
|
@ -1556,219 +1556,6 @@ namespace Kurs.Platform.Migrations
|
||||||
b.ToTable("PCity", (string)null);
|
b.ToTable("PCity", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassAttandance", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<DateTime>("JoinTime")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LeaveTime")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<Guid>("SessionId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<Guid?>("StudentId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("StudentName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.Property<int>("TotalDurationMinutes")
|
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("JoinTime");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId");
|
|
||||||
|
|
||||||
b.HasIndex("StudentId");
|
|
||||||
|
|
||||||
b.ToTable("PClassAttandance", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassChat", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsTeacher")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<string>("Message")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(2000)
|
|
||||||
.HasColumnType("nvarchar(2000)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("SenderId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("SenderName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.Property<Guid>("SessionId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<DateTime>("Timestamp")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("SenderId");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId");
|
|
||||||
|
|
||||||
b.HasIndex("Timestamp");
|
|
||||||
|
|
||||||
b.ToTable("PClassChat", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassParticipant", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("ConnectionId")
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.Property<DateTime>("CreationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("CreationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("CreatorId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("CreatorId");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<bool>("IsAudioMuted")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<bool>("IsDeleted")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("bit")
|
|
||||||
.HasDefaultValue(false)
|
|
||||||
.HasColumnName("IsDeleted");
|
|
||||||
|
|
||||||
b.Property<bool>("IsTeacher")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<bool>("IsVideoMuted")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<DateTime>("JoinTime")
|
|
||||||
.HasColumnType("datetime2");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("LastModificationTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("LastModificationTime");
|
|
||||||
|
|
||||||
b.Property<Guid?>("LastModifierId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("LastModifierId");
|
|
||||||
|
|
||||||
b.Property<Guid>("SessionId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("UserEmail")
|
|
||||||
.HasMaxLength(200)
|
|
||||||
.HasColumnType("nvarchar(200)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("UserId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(100)
|
|
||||||
.HasColumnType("nvarchar(100)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId");
|
|
||||||
|
|
||||||
b.HasIndex("UserId");
|
|
||||||
|
|
||||||
b.HasIndex("SessionId", "UserId")
|
|
||||||
.IsUnique()
|
|
||||||
.HasFilter("[UserId] IS NOT NULL");
|
|
||||||
|
|
||||||
b.ToTable("PClassParticipant", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Classroom", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Classroom", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -1858,6 +1645,227 @@ namespace Kurs.Platform.Migrations
|
||||||
b.ToTable("PClassroom", (string)null);
|
b.ToTable("PClassroom", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LeaveTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<Guid>("SessionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<Guid?>("StudentId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("StudentName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<int>("TotalDurationMinutes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("JoinTime");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId");
|
||||||
|
|
||||||
|
b.HasIndex("StudentId");
|
||||||
|
|
||||||
|
b.ToTable("PClassroomAttandance", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("IsTeacher")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2000)
|
||||||
|
.HasColumnType("nvarchar(2000)");
|
||||||
|
|
||||||
|
b.Property<string>("MessageType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("RecipientId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("SenderId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("SenderName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<Guid>("SessionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Timestamp")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SenderId");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId");
|
||||||
|
|
||||||
|
b.HasIndex("Timestamp");
|
||||||
|
|
||||||
|
b.ToTable("PClassroomChat", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("ConnectionId")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("CreationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatorId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("CreatorId");
|
||||||
|
|
||||||
|
b.Property<Guid?>("DeleterId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("DeleterId");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("DeletionTime");
|
||||||
|
|
||||||
|
b.Property<bool>("IsAudioMuted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<bool>("IsHandRaised")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsTeacher")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsVideoMuted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime>("JoinTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<Guid>("SessionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UserId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.HasIndex("SessionId", "UserId")
|
||||||
|
.IsUnique()
|
||||||
|
.HasFilter("[UserId] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("PClassroomParticipant", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -6555,7 +6563,7 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Country");
|
b.Navigation("Country");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassAttandance", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
||||||
.WithMany("AttendanceRecords")
|
.WithMany("AttendanceRecords")
|
||||||
|
|
@ -6566,7 +6574,7 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Session");
|
b.Navigation("Session");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassChat", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
||||||
.WithMany("ChatMessages")
|
.WithMany("ChatMessages")
|
||||||
|
|
@ -6577,7 +6585,7 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Session");
|
b.Navigation("Session");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassParticipant", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
b.HasOne("Kurs.Platform.Entities.Classroom", "Session")
|
||||||
.WithMany("Participants")
|
.WithMany("Participants")
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,18 @@ namespace Kurs.Platform.SignalR.Hubs;
|
||||||
public class ClassroomHub : Hub
|
public class ClassroomHub : Hub
|
||||||
{
|
{
|
||||||
private readonly IRepository<Classroom, Guid> _classSessionRepository;
|
private readonly IRepository<Classroom, Guid> _classSessionRepository;
|
||||||
private readonly IRepository<ClassParticipant, Guid> _participantRepository;
|
private readonly IRepository<ClassroomParticipant, Guid> _participantRepository;
|
||||||
private readonly IRepository<ClassChat, Guid> _chatMessageRepository;
|
private readonly IRepository<ClassroomChat, Guid> _chatMessageRepository;
|
||||||
|
private readonly IRepository<ClassroomAttandance, Guid> _attendanceRepository;
|
||||||
private readonly ILogger<ClassroomHub> _logger;
|
private readonly ILogger<ClassroomHub> _logger;
|
||||||
private readonly IGuidGenerator _guidGenerator;
|
private readonly IGuidGenerator _guidGenerator;
|
||||||
private readonly ICurrentUser _currentUser;
|
private readonly ICurrentUser _currentUser;
|
||||||
|
|
||||||
public ClassroomHub(
|
public ClassroomHub(
|
||||||
IRepository<Classroom, Guid> classSessionRepository,
|
IRepository<Classroom, Guid> classSessionRepository,
|
||||||
IRepository<ClassParticipant, Guid> participantRepository,
|
IRepository<ClassroomParticipant, Guid> participantRepository,
|
||||||
IRepository<ClassChat, Guid> chatMessageRepository,
|
IRepository<ClassroomChat, Guid> chatMessageRepository,
|
||||||
|
IRepository<ClassroomAttandance, Guid> attendanceRepository,
|
||||||
ILogger<ClassroomHub> logger,
|
ILogger<ClassroomHub> logger,
|
||||||
IGuidGenerator guidGenerator,
|
IGuidGenerator guidGenerator,
|
||||||
ICurrentUser currentUser)
|
ICurrentUser currentUser)
|
||||||
|
|
@ -31,91 +33,93 @@ public class ClassroomHub : Hub
|
||||||
_classSessionRepository = classSessionRepository;
|
_classSessionRepository = classSessionRepository;
|
||||||
_participantRepository = participantRepository;
|
_participantRepository = participantRepository;
|
||||||
_chatMessageRepository = chatMessageRepository;
|
_chatMessageRepository = chatMessageRepository;
|
||||||
|
_attendanceRepository = attendanceRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_guidGenerator = guidGenerator;
|
_guidGenerator = guidGenerator;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HubMethodName("JoinClass")]
|
[HubMethodName("JoinClass")]
|
||||||
public async Task JoinClassAsync(Guid sessionId, string userName)
|
public async Task JoinClassAsync(Guid sessionId, Guid userId, string userName, bool isTeacher)
|
||||||
{
|
{
|
||||||
var classSession = await _classSessionRepository.GetAsync(sessionId);
|
|
||||||
|
|
||||||
// Add to SignalR group
|
|
||||||
await Groups.AddToGroupAsync(Context.ConnectionId, sessionId.ToString());
|
|
||||||
|
|
||||||
// Update participant connection
|
|
||||||
var participant = await _participantRepository.FirstOrDefaultAsync(
|
var participant = await _participantRepository.FirstOrDefaultAsync(
|
||||||
x => x.SessionId == sessionId && x.UserId == _currentUser.Id
|
x => x.SessionId == sessionId && x.UserId == userId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (participant != null)
|
if (participant == null)
|
||||||
|
{
|
||||||
|
participant = new ClassroomParticipant(
|
||||||
|
_guidGenerator.Create(),
|
||||||
|
sessionId,
|
||||||
|
userId,
|
||||||
|
userName,
|
||||||
|
isTeacher
|
||||||
|
);
|
||||||
|
participant.UpdateConnectionId(Context.ConnectionId);
|
||||||
|
await _participantRepository.InsertAsync(participant, autoSave: true);
|
||||||
|
|
||||||
|
// 🔑 Katılımcı sayısını güncelle
|
||||||
|
var classroom = await _classSessionRepository.GetAsync(sessionId);
|
||||||
|
var participantCount = await _participantRepository.CountAsync(x => x.SessionId == sessionId);
|
||||||
|
classroom.ParticipantCount = participantCount;
|
||||||
|
await _classSessionRepository.UpdateAsync(classroom, autoSave: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
participant.UpdateConnectionId(Context.ConnectionId);
|
participant.UpdateConnectionId(Context.ConnectionId);
|
||||||
await _participantRepository.UpdateAsync(participant);
|
await _participantRepository.UpdateAsync(participant, autoSave: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify others
|
// 🔑 Attendance kaydı aç
|
||||||
|
var attendance = new ClassroomAttandance(
|
||||||
|
_guidGenerator.Create(),
|
||||||
|
sessionId,
|
||||||
|
userId,
|
||||||
|
userName,
|
||||||
|
DateTime.UtcNow
|
||||||
|
);
|
||||||
|
await _attendanceRepository.InsertAsync(attendance, autoSave: true);
|
||||||
|
|
||||||
|
await Groups.AddToGroupAsync(Context.ConnectionId, sessionId.ToString());
|
||||||
|
|
||||||
await Clients.Group(sessionId.ToString())
|
await Clients.Group(sessionId.ToString())
|
||||||
.SendAsync("ParticipantJoined", _currentUser.Id, userName);
|
.SendAsync("ParticipantJoined", userId, userName);
|
||||||
_logger.LogInformation($"User {userName} joined class {sessionId}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HubMethodName("LeaveClass")]
|
[HubMethodName("LeaveClass")]
|
||||||
public async Task LeaveClassAsync(Guid sessionId)
|
public async Task LeaveClassAsync(Guid sessionId)
|
||||||
{
|
{
|
||||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, sessionId.ToString());
|
await Groups.RemoveFromGroupAsync(Context.ConnectionId, sessionId.ToString());
|
||||||
|
|
||||||
|
var userId = _currentUser.Id;
|
||||||
|
if (userId.HasValue)
|
||||||
|
{
|
||||||
|
var attendance = await _attendanceRepository.FirstOrDefaultAsync(
|
||||||
|
x => x.SessionId == sessionId && x.StudentId == userId.Value && x.LeaveTime == null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (attendance != null)
|
||||||
|
{
|
||||||
|
attendance.LeaveTime = DateTime.UtcNow;
|
||||||
|
attendance.TotalDurationMinutes = (int)Math.Max(
|
||||||
|
1,
|
||||||
|
(attendance.LeaveTime.Value - attendance.JoinTime).TotalMinutes
|
||||||
|
);
|
||||||
|
await _attendanceRepository.UpdateAsync(attendance, autoSave: true);
|
||||||
|
|
||||||
|
await Clients.Group(sessionId.ToString())
|
||||||
|
.SendAsync("AttendanceUpdated", attendance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await Clients.Group(sessionId.ToString())
|
await Clients.Group(sessionId.ToString())
|
||||||
.SendAsync("ParticipantLeft", _currentUser);
|
.SendAsync("ParticipantLeft", _currentUser);
|
||||||
_logger.LogInformation($"User {_currentUser} left class {sessionId}");
|
_logger.LogInformation($"User {_currentUser} left class {sessionId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendSignalingMessageAsync(SignalingMessageDto message)
|
[HubMethodName("MuteParticipant")]
|
||||||
{
|
public async Task MuteParticipantAsync(Guid sessionId, Guid userId, bool isMuted, bool isTeacher)
|
||||||
// Forward WebRTC signaling messages
|
|
||||||
await Clients.User(message.ToUserId)
|
|
||||||
.SendAsync("ReceiveSignalingMessage", message);
|
|
||||||
_logger.LogInformation($"Signaling message sent from {message.FromUserId} to {message.ToUserId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendChatMessageAsync(Guid sessionId, string message)
|
|
||||||
{
|
|
||||||
var userName = _currentUser.UserName;
|
|
||||||
var userId = _currentUser.Id;
|
|
||||||
|
|
||||||
// Check if user is teacher
|
|
||||||
var participant = await _participantRepository.FirstOrDefaultAsync(
|
|
||||||
x => x.SessionId == sessionId && x.UserId == userId
|
|
||||||
);
|
|
||||||
|
|
||||||
var isTeacher = participant?.IsTeacher ?? false;
|
|
||||||
|
|
||||||
// Save message to database
|
|
||||||
var chatMessage = new ClassChat(
|
|
||||||
_guidGenerator.Create(),
|
|
||||||
sessionId,
|
|
||||||
userId,
|
|
||||||
userName,
|
|
||||||
message,
|
|
||||||
isTeacher
|
|
||||||
);
|
|
||||||
|
|
||||||
await _chatMessageRepository.InsertAsync(chatMessage);
|
|
||||||
|
|
||||||
// Send to all participants
|
|
||||||
await Clients.Group(sessionId.ToString())
|
|
||||||
.SendAsync("ChatMessage", new
|
|
||||||
{
|
|
||||||
Id = chatMessage.Id,
|
|
||||||
SenderId = chatMessage.SenderId,
|
|
||||||
SenderName = chatMessage.SenderName,
|
|
||||||
Message = chatMessage.Message,
|
|
||||||
Timestamp = chatMessage.Timestamp,
|
|
||||||
IsTeacher = chatMessage.IsTeacher
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task MuteParticipantAsync(Guid sessionId, Guid participantId, bool isMuted)
|
|
||||||
{
|
{
|
||||||
var teacherParticipant = await _participantRepository.FirstOrDefaultAsync(
|
var teacherParticipant = await _participantRepository.FirstOrDefaultAsync(
|
||||||
x => x.SessionId == sessionId && x.UserId == _currentUser.Id
|
x => x.SessionId == sessionId && x.UserId == _currentUser.Id
|
||||||
|
|
@ -128,59 +132,264 @@ public class ClassroomHub : Hub
|
||||||
}
|
}
|
||||||
|
|
||||||
var participant = await _participantRepository.FirstOrDefaultAsync(
|
var participant = await _participantRepository.FirstOrDefaultAsync(
|
||||||
x => x.SessionId == sessionId && x.UserId == participantId
|
x => x.SessionId == sessionId && x.UserId == userId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (participant != null)
|
if (participant != null)
|
||||||
{
|
{
|
||||||
if (isMuted)
|
if (isMuted) participant.MuteAudio();
|
||||||
participant.MuteAudio();
|
else participant.UnmuteAudio();
|
||||||
else
|
|
||||||
participant.UnmuteAudio();
|
|
||||||
|
|
||||||
await _participantRepository.UpdateAsync(participant);
|
await _participantRepository.UpdateAsync(participant, autoSave: true);
|
||||||
|
|
||||||
// Notify the participant and others
|
|
||||||
await Clients.Group(sessionId.ToString())
|
await Clients.Group(sessionId.ToString())
|
||||||
.SendAsync("ParticipantMuted", participantId, isMuted);
|
.SendAsync("ParticipantMuted", userId, isMuted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HubMethodName("SendChatMessage")]
|
||||||
|
public async Task SendChatMessageAsync(
|
||||||
|
Guid sessionId,
|
||||||
|
Guid senderId,
|
||||||
|
string senderName,
|
||||||
|
string message,
|
||||||
|
bool isTeacher,
|
||||||
|
string messageType)
|
||||||
|
{
|
||||||
|
// Save message to DB
|
||||||
|
var chatMessage = new ClassroomChat(
|
||||||
|
_guidGenerator.Create(),
|
||||||
|
sessionId,
|
||||||
|
senderId,
|
||||||
|
senderName,
|
||||||
|
message,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
isTeacher,
|
||||||
|
messageType
|
||||||
|
);
|
||||||
|
|
||||||
|
await _chatMessageRepository.InsertAsync(chatMessage, autoSave: true);
|
||||||
|
|
||||||
|
// Broadcast to group
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("ChatMessage", new
|
||||||
|
{
|
||||||
|
Id = chatMessage.Id,
|
||||||
|
SenderId = senderId,
|
||||||
|
SenderName = senderName,
|
||||||
|
Message = chatMessage.Message,
|
||||||
|
Timestamp = chatMessage.Timestamp,
|
||||||
|
IsTeacher = isTeacher,
|
||||||
|
MessageType = messageType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName("SendPrivateMessage")]
|
||||||
|
public async Task SendPrivateMessageAsync(
|
||||||
|
Guid sessionId,
|
||||||
|
Guid senderId,
|
||||||
|
string senderName,
|
||||||
|
string message,
|
||||||
|
Guid recipientId,
|
||||||
|
string recipientName,
|
||||||
|
bool isTeacher,
|
||||||
|
string messageType)
|
||||||
|
{
|
||||||
|
// Save message to DB
|
||||||
|
var chatMessage = new ClassroomChat(
|
||||||
|
_guidGenerator.Create(),
|
||||||
|
sessionId,
|
||||||
|
senderId,
|
||||||
|
senderName,
|
||||||
|
message,
|
||||||
|
recipientId,
|
||||||
|
recipientName,
|
||||||
|
isTeacher,
|
||||||
|
"private"
|
||||||
|
);
|
||||||
|
|
||||||
|
await _chatMessageRepository.InsertAsync(chatMessage, autoSave: true);
|
||||||
|
|
||||||
|
await Clients.User(recipientId.ToString()).SendAsync("ChatMessage", new
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
SenderId = senderId,
|
||||||
|
SenderName = senderName,
|
||||||
|
Message = message,
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
IsTeacher = isTeacher,
|
||||||
|
RecipientId = recipientId,
|
||||||
|
RecipientName = recipientName,
|
||||||
|
MessageType = "private"
|
||||||
|
});
|
||||||
|
|
||||||
|
await Clients.Caller.SendAsync("ChatMessage", new
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
SenderId = senderId,
|
||||||
|
SenderName = senderName,
|
||||||
|
Message = message,
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
IsTeacher = isTeacher,
|
||||||
|
RecipientId = recipientId,
|
||||||
|
RecipientName = recipientName,
|
||||||
|
MessageType = "private"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName("SendAnnouncement")]
|
||||||
|
public async Task SendAnnouncementAsync(Guid sessionId, Guid senderId, string senderName, string message, bool isTeacher)
|
||||||
|
{
|
||||||
|
// Save message to DB
|
||||||
|
var chatMessage = new ClassroomChat(
|
||||||
|
_guidGenerator.Create(),
|
||||||
|
sessionId,
|
||||||
|
senderId,
|
||||||
|
senderName,
|
||||||
|
message,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
isTeacher,
|
||||||
|
"announcement"
|
||||||
|
);
|
||||||
|
|
||||||
|
await _chatMessageRepository.InsertAsync(chatMessage, autoSave: true);
|
||||||
|
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("ChatMessage", new
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
SenderId = senderId,
|
||||||
|
SenderName = senderName,
|
||||||
|
Message = message,
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
IsTeacher = isTeacher,
|
||||||
|
MessageType = "announcement"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName("RaiseHand")]
|
||||||
|
public async Task RaiseHandAsync(Guid sessionId, Guid studentId, string studentName)
|
||||||
|
{
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("HandRaiseReceived", new
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
StudentId = studentId,
|
||||||
|
StudentName = studentName,
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
IsActive = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName("KickParticipant")]
|
||||||
|
public async Task KickParticipantAsync(Guid sessionId, Guid participantId)
|
||||||
|
{
|
||||||
|
// Attendance kapat
|
||||||
|
var attendance = await _attendanceRepository.FirstOrDefaultAsync(
|
||||||
|
x => x.SessionId == sessionId && x.StudentId == participantId && x.LeaveTime == null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (attendance != null)
|
||||||
|
{
|
||||||
|
attendance.LeaveTime = DateTime.UtcNow;
|
||||||
|
attendance.TotalDurationMinutes = (int)Math.Max(
|
||||||
|
1,
|
||||||
|
(attendance.LeaveTime.Value - attendance.JoinTime).TotalMinutes
|
||||||
|
);
|
||||||
|
|
||||||
|
await _attendanceRepository.UpdateAsync(attendance, autoSave: true);
|
||||||
|
|
||||||
|
// Katılım güncellemesini yayınla
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("AttendanceUpdated", new
|
||||||
|
{
|
||||||
|
attendance.Id,
|
||||||
|
attendance.SessionId,
|
||||||
|
attendance.StudentId,
|
||||||
|
attendance.StudentName,
|
||||||
|
attendance.JoinTime,
|
||||||
|
attendance.LeaveTime,
|
||||||
|
attendance.TotalDurationMinutes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Katılımcı çıkışını bildir
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("ParticipantLeft", participantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName("ApproveHandRaise")]
|
||||||
|
public async Task ApproveHandRaiseAsync(Guid sessionId, Guid handRaiseId)
|
||||||
|
{
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("HandRaiseDismissed", handRaiseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HubMethodName("DismissHandRaise")]
|
||||||
|
public async Task DismissHandRaiseAsync(Guid sessionId, Guid handRaiseId)
|
||||||
|
{
|
||||||
|
await Clients.Group(sessionId.ToString()).SendAsync("HandRaiseDismissed", handRaiseId);
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task OnDisconnectedAsync(Exception exception)
|
public override async Task OnDisconnectedAsync(Exception exception)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// bağlantı gerçekten iptal edilmişse DB sorgusu çalıştırma
|
|
||||||
if (Context.ConnectionAborted.IsCancellationRequested)
|
if (Context.ConnectionAborted.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var userId = _currentUser.Id;
|
var userId = _currentUser.Id;
|
||||||
if (userId.HasValue)
|
if (userId.HasValue)
|
||||||
{
|
{
|
||||||
|
// 🔑 1. Katılımcı listesi
|
||||||
var participants = await _participantRepository
|
var participants = await _participantRepository
|
||||||
.GetListAsync(x => x.UserId == userId.Value && x.ConnectionId == Context.ConnectionId)
|
.GetListAsync(x => x.UserId == userId.Value && x.ConnectionId == Context.ConnectionId);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
foreach (var participant in participants)
|
foreach (var participant in participants)
|
||||||
{
|
{
|
||||||
|
// 🔑 2. Attendance kaydını kapat
|
||||||
|
var attendance = await _attendanceRepository.FirstOrDefaultAsync(
|
||||||
|
x => x.SessionId == participant.SessionId &&
|
||||||
|
x.StudentId == userId.Value &&
|
||||||
|
x.LeaveTime == null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (attendance != null)
|
||||||
|
{
|
||||||
|
attendance.LeaveTime = DateTime.UtcNow;
|
||||||
|
attendance.TotalDurationMinutes = (int)Math.Max(
|
||||||
|
1,
|
||||||
|
(attendance.LeaveTime.Value - attendance.JoinTime).TotalMinutes
|
||||||
|
);
|
||||||
|
|
||||||
|
await _attendanceRepository.UpdateAsync(attendance, autoSave: true);
|
||||||
|
|
||||||
|
// Frontend’e bildir
|
||||||
|
await Clients.Group(participant.SessionId.ToString())
|
||||||
|
.SendAsync("AttendanceUpdated", new
|
||||||
|
{
|
||||||
|
attendance.Id,
|
||||||
|
attendance.SessionId,
|
||||||
|
attendance.StudentId,
|
||||||
|
attendance.StudentName,
|
||||||
|
attendance.JoinTime,
|
||||||
|
attendance.LeaveTime,
|
||||||
|
attendance.TotalDurationMinutes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔑 3. ParticipantLeft event’i
|
||||||
await Clients.Group(participant.SessionId.ToString())
|
await Clients.Group(participant.SessionId.ToString())
|
||||||
.SendAsync("ParticipantLeft", userId.Value)
|
.SendAsync("ParticipantLeft", userId.Value);
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
{
|
{
|
||||||
// bağlantı kapandığında doğal, error yerine debug seviyesinde loglayın
|
|
||||||
_logger.LogDebug("OnDisconnectedAsync iptal edildi (connection aborted).");
|
_logger.LogDebug("OnDisconnectedAsync iptal edildi (connection aborted).");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// beklenmeyen hataları error olarak loglayın
|
|
||||||
_logger.LogError(ex, "OnDisconnectedAsync hata");
|
_logger.LogError(ex, "OnDisconnectedAsync hata");
|
||||||
}
|
}
|
||||||
|
|
||||||
await base.OnDisconnectedAsync(exception).ConfigureAwait(false);
|
await base.OnDisconnectedAsync(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.b9bfk61okp"
|
"revision": "0.48gll4p3s3o"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { ClassAttendanceDto } from '@/proxy/classroom/models'
|
import { ClassroomAttendanceDto } from '@/proxy/classroom/models'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { FaClock, FaUsers } from 'react-icons/fa'
|
import { FaClock, FaUsers } from 'react-icons/fa'
|
||||||
|
|
||||||
interface AttendancePanelProps {
|
interface AttendancePanelProps {
|
||||||
attendanceRecords: ClassAttendanceDto[]
|
attendanceRecords: ClassroomAttendanceDto[]
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { ClassChatDto } from '@/proxy/classroom/models'
|
import { ClassroomChatDto } from '@/proxy/classroom/models'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
import React, { useState, useRef, useEffect } from 'react'
|
import React, { useState, useRef, useEffect } from 'react'
|
||||||
import { FaPaperPlane, FaComments, FaTimes, FaUsers, FaUser, FaBullhorn } from 'react-icons/fa'
|
import { FaPaperPlane, FaComments, FaTimes, FaUsers, FaUser, FaBullhorn } from 'react-icons/fa'
|
||||||
|
|
||||||
interface ChatPanelProps {
|
interface ChatPanelProps {
|
||||||
messages: ClassChatDto[]
|
messages: ClassroomChatDto[]
|
||||||
isTeacher: boolean
|
isTeacher: boolean
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { FaMicrophoneSlash, FaExpand, FaUserTimes } from 'react-icons/fa'
|
import { FaMicrophoneSlash, FaExpand, FaUserTimes } from 'react-icons/fa'
|
||||||
import { VideoPlayer } from './VideoPlayer'
|
import { VideoPlayer } from './VideoPlayer'
|
||||||
import { ClassParticipantDto, VideoLayoutDto } from '@/proxy/classroom/models'
|
import { ClassroomParticipantDto, VideoLayoutDto } from '@/proxy/classroom/models'
|
||||||
|
|
||||||
interface ParticipantGridProps {
|
interface ParticipantGridProps {
|
||||||
participants: ClassParticipantDto[]
|
participants: ClassroomParticipantDto[]
|
||||||
localStream?: MediaStream
|
localStream?: MediaStream
|
||||||
currentUserId: string
|
currentUserId: string
|
||||||
currentUserName: string
|
currentUserName: string
|
||||||
|
|
@ -14,7 +14,7 @@ interface ParticipantGridProps {
|
||||||
onToggleAudio: () => void
|
onToggleAudio: () => void
|
||||||
onToggleVideo: () => void
|
onToggleVideo: () => void
|
||||||
onLeaveCall: () => void
|
onLeaveCall: () => void
|
||||||
onMuteParticipant?: (participantId: string, isMuted: boolean) => void
|
onMuteParticipant?: (participantId: string, isMuted: boolean, isTeacher: boolean) => void
|
||||||
layout: VideoLayoutDto
|
layout: VideoLayoutDto
|
||||||
focusedParticipant?: string
|
focusedParticipant?: string
|
||||||
onParticipantFocus?: (participantId: string | undefined) => void
|
onParticipantFocus?: (participantId: string | undefined) => void
|
||||||
|
|
@ -211,7 +211,7 @@ export const ParticipantGrid: React.FC<ParticipantGridProps> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderParticipant = (
|
const renderParticipant = (
|
||||||
participant: ClassParticipantDto,
|
participant: ClassroomParticipantDto,
|
||||||
isMain: boolean = false,
|
isMain: boolean = false,
|
||||||
isSmall: boolean = false,
|
isSmall: boolean = false,
|
||||||
) => (
|
) => (
|
||||||
|
|
@ -243,7 +243,7 @@ export const ParticipantGrid: React.FC<ParticipantGridProps> = ({
|
||||||
<button
|
<button
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
onMuteParticipant?.(participant.id, !participant.isAudioMuted)
|
onMuteParticipant?.(participant.id, !participant.isAudioMuted, isTeacher)
|
||||||
}}
|
}}
|
||||||
className={`p-1 rounded-full text-white text-xs ${
|
className={`p-1 rounded-full text-white text-xs ${
|
||||||
participant.isAudioMuted ? 'bg-red-600' : 'bg-gray-600 hover:bg-gray-700'
|
participant.isAudioMuted ? 'bg-red-600' : 'bg-gray-600 hover:bg-gray-700'
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ export interface ClassroomSettingsDto {
|
||||||
autoMuteNewParticipants: boolean
|
autoMuteNewParticipants: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClassAttendanceDto {
|
export interface ClassroomAttendanceDto {
|
||||||
id: string
|
id: string
|
||||||
sessionId: string
|
sessionId: string
|
||||||
studentId: string
|
studentId: string
|
||||||
|
|
@ -49,16 +49,7 @@ export interface ClassAttendanceDto {
|
||||||
totalDurationMinutes: number
|
totalDurationMinutes: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MediaType = 'audio' | 'video' | 'screen'
|
export interface ClassroomParticipantDto {
|
||||||
|
|
||||||
export interface SignalingMessageDto {
|
|
||||||
type: MediaType
|
|
||||||
fromUserId: string
|
|
||||||
toUserId: string
|
|
||||||
data: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClassParticipantDto {
|
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
isTeacher: boolean
|
isTeacher: boolean
|
||||||
|
|
@ -73,7 +64,7 @@ export interface ClassParticipantDto {
|
||||||
|
|
||||||
export type messageType = 'public' | 'private' | 'announcement'
|
export type messageType = 'public' | 'private' | 'announcement'
|
||||||
|
|
||||||
export interface ClassChatDto {
|
export interface ClassroomChatDto {
|
||||||
id: string
|
id: string
|
||||||
senderId: string
|
senderId: string
|
||||||
senderName: string
|
senderName: string
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,14 @@
|
||||||
import {
|
import { ClassroomAttendanceDto, ClassroomChatDto, HandRaiseDto } from '@/proxy/classroom/models'
|
||||||
ClassAttendanceDto,
|
|
||||||
ClassChatDto,
|
|
||||||
HandRaiseDto,
|
|
||||||
SignalingMessageDto,
|
|
||||||
} from '@/proxy/classroom/models'
|
|
||||||
import { store } from '@/store/store'
|
import { store } from '@/store/store'
|
||||||
import * as signalR from '@microsoft/signalr'
|
import * as signalR from '@microsoft/signalr'
|
||||||
|
|
||||||
export class SignalRService {
|
export class SignalRService {
|
||||||
private connection!: signalR.HubConnection
|
private connection!: signalR.HubConnection
|
||||||
private isConnected: boolean = false
|
private isConnected: boolean = false
|
||||||
private onSignalingMessage?: (message: SignalingMessageDto) => void
|
private onAttendanceUpdate?: (record: ClassroomAttendanceDto) => void
|
||||||
private onAttendanceUpdate?: (record: ClassAttendanceDto) => void
|
|
||||||
private onParticipantJoined?: (userId: string, name: string) => void
|
private onParticipantJoined?: (userId: string, name: string) => void
|
||||||
private onParticipantLeft?: (userId: string) => void
|
private onParticipantLeft?: (userId: string) => void
|
||||||
private onChatMessage?: (message: ClassChatDto) => void
|
private onChatMessage?: (message: ClassroomChatDto) => void
|
||||||
private onParticipantMuted?: (userId: string, isMuted: boolean) => void
|
private onParticipantMuted?: (userId: string, isMuted: boolean) => void
|
||||||
private onHandRaiseReceived?: (handRaise: HandRaiseDto) => void
|
private onHandRaiseReceived?: (handRaise: HandRaiseDto) => void
|
||||||
private onHandRaiseDismissed?: (handRaiseId: string) => void
|
private onHandRaiseDismissed?: (handRaiseId: string) => void
|
||||||
|
|
@ -38,11 +32,7 @@ export class SignalRService {
|
||||||
private setupEventHandlers() {
|
private setupEventHandlers() {
|
||||||
if (!this.connection) return
|
if (!this.connection) return
|
||||||
|
|
||||||
this.connection.on('ReceiveSignalingMessage', (message: SignalingMessageDto) => {
|
this.connection.on('AttendanceUpdated', (record: ClassroomAttendanceDto) => {
|
||||||
this.onSignalingMessage?.(message)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.connection.on('AttendanceUpdated', (record: ClassAttendanceDto) => {
|
|
||||||
this.onAttendanceUpdate?.(record)
|
this.onAttendanceUpdate?.(record)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -95,16 +85,21 @@ export class SignalRService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async joinClass(sessionId: string, userName: string): Promise<void> {
|
async joinClass(
|
||||||
|
sessionId: string,
|
||||||
|
userId: string,
|
||||||
|
userName: string,
|
||||||
|
isTeacher: boolean,
|
||||||
|
): Promise<void> {
|
||||||
if (!this.isConnected) {
|
if (!this.isConnected) {
|
||||||
console.log('Error starting SignalR connection join class for', userName)
|
console.log('Error starting SignalR connection join class for', userName)
|
||||||
// Simulate successful join in demo mode
|
|
||||||
// Don't auto-add participants in demo mode - let manual simulation handle this
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Joining class session:', sessionId, 'as', userName, 'isTeacher:', isTeacher)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.connection.invoke('JoinClass', sessionId, userName)
|
await this.connection.invoke('JoinClass', sessionId, userId, userName, isTeacher)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error joining class:', error)
|
console.error('Error joining class:', error)
|
||||||
}
|
}
|
||||||
|
|
@ -129,21 +124,6 @@ export class SignalRService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendSignalingMessage(message: SignalingMessageDto): Promise<void> {
|
|
||||||
if (!this.isConnected) {
|
|
||||||
console.log('Error starting SignalR connection signaling message', message.type)
|
|
||||||
// In demo mode, we can't send real signaling messages
|
|
||||||
// WebRTC will need to work in local-only mode
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.connection.invoke('SendSignalingMessage', message)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error sending signaling message:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async sendChatMessage(
|
async sendChatMessage(
|
||||||
sessionId: string,
|
sessionId: string,
|
||||||
senderId: string,
|
senderId: string,
|
||||||
|
|
@ -153,8 +133,8 @@ export class SignalRService {
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!this.isConnected) {
|
if (!this.isConnected) {
|
||||||
console.log('Error starting SignalR connection simulating chat message from', senderName)
|
console.log('Error starting SignalR connection simulating chat message from', senderName)
|
||||||
const chatMessage: ClassChatDto = {
|
const chatMessage: ClassroomChatDto = {
|
||||||
id: `msg-${Date.now()}`,
|
id: crypto.randomUUID(),
|
||||||
senderId,
|
senderId,
|
||||||
senderName,
|
senderName,
|
||||||
message,
|
message,
|
||||||
|
|
@ -199,8 +179,8 @@ export class SignalRService {
|
||||||
'to',
|
'to',
|
||||||
recipientName,
|
recipientName,
|
||||||
)
|
)
|
||||||
const chatMessage: ClassChatDto = {
|
const chatMessage: ClassroomChatDto = {
|
||||||
id: `msg-${Date.now()}`,
|
id: crypto.randomUUID(),
|
||||||
senderId,
|
senderId,
|
||||||
senderName,
|
senderName,
|
||||||
message,
|
message,
|
||||||
|
|
@ -226,6 +206,7 @@ export class SignalRService {
|
||||||
recipientId,
|
recipientId,
|
||||||
recipientName,
|
recipientName,
|
||||||
isTeacher,
|
isTeacher,
|
||||||
|
'private',
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error sending private message:', error)
|
console.error('Error sending private message:', error)
|
||||||
|
|
@ -237,16 +218,17 @@ export class SignalRService {
|
||||||
senderId: string,
|
senderId: string,
|
||||||
senderName: string,
|
senderName: string,
|
||||||
message: string,
|
message: string,
|
||||||
|
isTeacher: boolean,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!this.isConnected) {
|
if (!this.isConnected) {
|
||||||
console.log('Error starting SignalR connection simulating announcement from', senderName)
|
console.log('Error starting SignalR connection simulating announcement from', senderName)
|
||||||
const chatMessage: ClassChatDto = {
|
const chatMessage: ClassroomChatDto = {
|
||||||
id: `msg-${Date.now()}`,
|
id: crypto.randomUUID(),
|
||||||
senderId,
|
senderId,
|
||||||
senderName,
|
senderName,
|
||||||
message,
|
message,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
isTeacher: true,
|
isTeacher,
|
||||||
messageType: 'announcement',
|
messageType: 'announcement',
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -256,13 +238,25 @@ export class SignalRService {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.connection.invoke('SendAnnouncement', sessionId, senderId, senderName, message)
|
await this.connection.invoke(
|
||||||
|
'SendAnnouncement',
|
||||||
|
sessionId,
|
||||||
|
senderId,
|
||||||
|
senderName,
|
||||||
|
message,
|
||||||
|
isTeacher,
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error sending chat message:', error)
|
console.error('Error sending chat message:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async muteParticipant(sessionId: string, userId: string, isMuted: boolean): Promise<void> {
|
async muteParticipant(
|
||||||
|
sessionId: string,
|
||||||
|
userId: string,
|
||||||
|
isMuted: boolean,
|
||||||
|
isTeacher: boolean,
|
||||||
|
): Promise<void> {
|
||||||
if (!this.isConnected) {
|
if (!this.isConnected) {
|
||||||
console.log('Error starting SignalR connection simulating mute participant', userId, isMuted)
|
console.log('Error starting SignalR connection simulating mute participant', userId, isMuted)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -271,8 +265,10 @@ export class SignalRService {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Muting participant:', userId, 'Muted:', isMuted, 'isTeacher:', isTeacher)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.connection.invoke('MuteParticipant', sessionId, userId, isMuted)
|
await this.connection.invoke('MuteParticipant', sessionId, userId, isMuted, isTeacher)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error muting participant:', error)
|
console.error('Error muting participant:', error)
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +278,7 @@ export class SignalRService {
|
||||||
if (!this.isConnected) {
|
if (!this.isConnected) {
|
||||||
console.log('Error starting SignalR connection simulating hand raise from', studentName)
|
console.log('Error starting SignalR connection simulating hand raise from', studentName)
|
||||||
const handRaise: HandRaiseDto = {
|
const handRaise: HandRaiseDto = {
|
||||||
id: `hand-${Date.now()}`,
|
id: crypto.randomUUID(),
|
||||||
studentId,
|
studentId,
|
||||||
studentName,
|
studentName,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
|
|
@ -349,11 +345,7 @@ export class SignalRService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setSignalingHandler(callback: (message: SignalingMessageDto) => void) {
|
setAttendanceUpdatedHandler(callback: (record: ClassroomAttendanceDto) => void) {
|
||||||
this.onSignalingMessage = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
setAttendanceUpdatedHandler(callback: (record: ClassAttendanceDto) => void) {
|
|
||||||
this.onAttendanceUpdate = callback
|
this.onAttendanceUpdate = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,7 +357,7 @@ export class SignalRService {
|
||||||
this.onParticipantLeft = callback
|
this.onParticipantLeft = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
setChatMessageReceivedHandler(callback: (message: ClassChatDto) => void) {
|
setChatMessageReceivedHandler(callback: (message: ClassroomChatDto) => void) {
|
||||||
this.onChatMessage = callback
|
this.onChatMessage = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export function useClassroomLogic() {
|
||||||
const handleCreateClass = (classData: Partial<ClassroomDto>) => {
|
const handleCreateClass = (classData: Partial<ClassroomDto>) => {
|
||||||
const newClass = {
|
const newClass = {
|
||||||
...classData,
|
...classData,
|
||||||
id: `class-${Date.now()}`,
|
id: crypto.randomUUID(),
|
||||||
teacherId: '',
|
teacherId: '',
|
||||||
teacherName: '',
|
teacherName: '',
|
||||||
isActive: false,
|
isActive: false,
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -5,9 +5,13 @@ import { Role } from '@/proxy/classroom/models'
|
||||||
import { useStoreActions, useStoreState } from '@/store/store'
|
import { useStoreActions, useStoreState } from '@/store/store'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { Helmet } from 'react-helmet'
|
||||||
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
import { Container } from '@/components/shared'
|
||||||
|
|
||||||
const Dashboard: React.FC = () => {
|
const Dashboard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const { translate } = useLocalization()
|
||||||
const { user } = useStoreState((state) => state.auth)
|
const { user } = useStoreState((state) => state.auth)
|
||||||
const { setUser } = useStoreActions((actions) => actions.auth.user)
|
const { setUser } = useStoreActions((actions) => actions.auth.user)
|
||||||
|
|
||||||
|
|
@ -21,56 +25,63 @@ const Dashboard: React.FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center p-4">
|
<>
|
||||||
<motion.div
|
<Helmet
|
||||||
initial={{ opacity: 0, y: 20 }}
|
titleTemplate="%s | Kurs Platform"
|
||||||
animate={{ opacity: 1, y: 0 }}
|
title={translate('::' + 'App.Classroom')}
|
||||||
className="text-center w-full max-w-4xl"
|
defaultTitle="Kurs Platform"
|
||||||
>
|
></Helmet>
|
||||||
<p className="text-lg sm:text-xl text-gray-600 mb-8 sm:mb-12">Lütfen rolünüzü seçin</p>
|
<Container>
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
className="text-center w-full max-w-4xl"
|
||||||
|
>
|
||||||
|
<p className="text-lg sm:text-xl text-gray-600 mb-8 sm:mb-12">Lütfen rolünüzü seçin</p>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 sm:gap-8">
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
onClick={() => handleRoleSelect('teacher')}
|
onClick={() => handleRoleSelect('teacher')}
|
||||||
className="bg-white rounded-lg shadow-lg p-6 sm:p-8 hover:shadow-xl transition-all duration-300 border-2 border-transparent hover:border-blue-500"
|
className="bg-white rounded-lg shadow-lg p-6 sm:p-8 hover:shadow-xl transition-all duration-300 border-2 border-transparent hover:border-blue-500"
|
||||||
>
|
>
|
||||||
<FaGraduationCap size={48} className="mx-auto text-blue-600 mb-4 sm:mb-4" />
|
<FaGraduationCap size={48} className="mx-auto text-blue-600 mb-4 sm:mb-4" />
|
||||||
<h2 className="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Öğretmen</h2>
|
<h2 className="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Öğretmen</h2>
|
||||||
<p className="text-gray-600 text-sm sm:text-base">
|
<p className="text-gray-600 text-sm sm:text-base">
|
||||||
Ders başlatın, öğrencilerle iletişim kurun ve katılım raporlarını görün
|
Ders başlatın, öğrencilerle iletişim kurun ve katılım raporlarını görün
|
||||||
</p>
|
</p>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
onClick={() => handleRoleSelect('student')}
|
onClick={() => handleRoleSelect('student')}
|
||||||
className="bg-white rounded-lg shadow-lg p-6 sm:p-8 hover:shadow-xl transition-all duration-300 border-2 border-transparent hover:border-green-500"
|
className="bg-white rounded-lg shadow-lg p-6 sm:p-8 hover:shadow-xl transition-all duration-300 border-2 border-transparent hover:border-green-500"
|
||||||
>
|
>
|
||||||
<FaUserCheck size={48} className="mx-auto text-green-600 mb-4 sm:mb-4" />
|
<FaUserCheck size={48} className="mx-auto text-green-600 mb-4 sm:mb-4" />
|
||||||
<h2 className="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Öğrenci</h2>
|
<h2 className="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Öğrenci</h2>
|
||||||
<p className="text-gray-600 text-sm sm:text-base">
|
<p className="text-gray-600 text-sm sm:text-base">
|
||||||
Aktif derslere katılın, öğretmeniniz ve diğer öğrencilerle etkileşim kurun
|
Aktif derslere katılın, öğretmeniniz ve diğer öğrencilerle etkileşim kurun
|
||||||
</p>
|
</p>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
|
|
||||||
<motion.button
|
<motion.button
|
||||||
whileHover={{ scale: 1.05 }}
|
whileHover={{ scale: 1.05 }}
|
||||||
whileTap={{ scale: 0.95 }}
|
whileTap={{ scale: 0.95 }}
|
||||||
onClick={() => handleRoleSelect('observer')}
|
onClick={() => handleRoleSelect('observer')}
|
||||||
className="bg-white rounded-lg shadow-lg p-6 sm:p-8 hover:shadow-xl transition-all duration-300 border-2 border-transparent hover:border-purple-500 md:col-span-2 lg:col-span-1"
|
className="bg-white rounded-lg shadow-lg p-6 sm:p-8 hover:shadow-xl transition-all duration-300 border-2 border-transparent hover:border-purple-500 md:col-span-2 lg:col-span-1"
|
||||||
>
|
>
|
||||||
<FaEye size={48} className="mx-auto text-purple-600 mb-4 sm:mb-4" />
|
<FaEye size={48} className="mx-auto text-purple-600 mb-4 sm:mb-4" />
|
||||||
<h2 className="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Gözlemci</h2>
|
<h2 className="text-xl sm:text-2xl font-bold text-gray-800 mb-2">Gözlemci</h2>
|
||||||
<p className="text-gray-600 text-sm sm:text-base">
|
<p className="text-gray-600 text-sm sm:text-base">
|
||||||
Sınıfı gözlemleyin, eğitim sürecini takip edin (ses/video paylaşımı yok)
|
Sınıfı gözlemleyin, eğitim sürecini takip edin (ses/video paylaşımı yok)
|
||||||
</p>
|
</p>
|
||||||
</motion.button>
|
</motion.button>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</Container>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue