Question Pool ve Question
This commit is contained in:
parent
f64f13557e
commit
7fdf4627d0
47 changed files with 2905 additions and 691 deletions
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Questions;
|
||||||
|
|
||||||
|
public class QuestionDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string QuestionType { get; set; }
|
||||||
|
public int Points { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
public string MediaUrl { get; set; }
|
||||||
|
public string MediaType { get; set; }
|
||||||
|
public string CorrectAnswer { get; set; }
|
||||||
|
public string Difficulty { get; set; }
|
||||||
|
public int TimeLimit { get; set; }
|
||||||
|
public string Explanation { get; set; }
|
||||||
|
|
||||||
|
public Guid QuestionPoolId { get; set; }
|
||||||
|
public List<QuestionOptionDto> Options { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Questions;
|
||||||
|
|
||||||
|
public class QuestionOptionDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string Text { get; set; }
|
||||||
|
public bool IsCorrect { get; set; }
|
||||||
|
|
||||||
|
public Guid QuestionId { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Questions;
|
||||||
|
|
||||||
|
public class QuestionPoolDto : FullAuditedEntityDto<Guid>
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string Tags { get; set; }
|
||||||
|
|
||||||
|
public List<QuestionDto> Questions { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using Kurs.Platform.Entities;
|
||||||
|
using Kurs.Platform.Questions;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Volo.Abp.Application.Dtos;
|
||||||
|
using Volo.Abp.Application.Services;
|
||||||
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using static Kurs.Platform.Data.Seeds.SeedConsts;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.DataSources;
|
||||||
|
|
||||||
|
public class QuestionAppService : CrudAppService<
|
||||||
|
Question,
|
||||||
|
QuestionDto,
|
||||||
|
Guid,
|
||||||
|
PagedAndSortedResultRequestDto>
|
||||||
|
{
|
||||||
|
public QuestionAppService(IRepository<Question, Guid> repo) : base(repo)
|
||||||
|
{
|
||||||
|
GetPolicyName = AppCodes.Definitions.Question;
|
||||||
|
GetListPolicyName = AppCodes.Definitions.Question;
|
||||||
|
CreatePolicyName = AppCodes.Definitions.Question + ".Create";
|
||||||
|
UpdatePolicyName = AppCodes.Definitions.Question + ".Update";
|
||||||
|
DeletePolicyName = AppCodes.Definitions.Question + ".Delete";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
using AutoMapper;
|
||||||
|
using Kurs.Platform.Entities;
|
||||||
|
using Kurs.Platform.Questions;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.DataSources;
|
||||||
|
|
||||||
|
public class QuestionAutoMapperProfile : Profile
|
||||||
|
{
|
||||||
|
public QuestionAutoMapperProfile()
|
||||||
|
{
|
||||||
|
CreateMap<Question, QuestionDto>().ReverseMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7881,10 +7881,22 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Classroom.Tag",
|
"key": "App.Definitions.Tag",
|
||||||
"tr": "Etiketler",
|
"tr": "Etiketler",
|
||||||
"en": "Tags"
|
"en": "Tags"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Definitions.QuestionPool",
|
||||||
|
"tr": "Soru Havuzu",
|
||||||
|
"en": "Question Pools"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"resourceName": "Platform",
|
||||||
|
"key": "App.Definitions.Question",
|
||||||
|
"tr": "Sorular",
|
||||||
|
"en": "Questions"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Definitions.RegistrationType",
|
"key": "App.Definitions.RegistrationType",
|
||||||
|
|
@ -11985,31 +11997,31 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Classroom",
|
"key": "App.Coordinator.Classroom",
|
||||||
"tr": "Sınıf",
|
"tr": "Sınıf",
|
||||||
"en": "Classroom"
|
"en": "Classroom"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Classroom.Dashboard",
|
"key": "App.Coordinator.Classroom.Dashboard",
|
||||||
"tr": "Gösterge Paneli",
|
"tr": "Gösterge Paneli",
|
||||||
"en": "Dashboard"
|
"en": "Dashboard"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Classroom.List",
|
"key": "App.Coordinator.Classroom.List",
|
||||||
"tr": "Sınıflar",
|
"tr": "Sınıflar",
|
||||||
"en": "Classes"
|
"en": "Classes"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Classroom.RoomDetail",
|
"key": "App.Coordinator.Classroom.RoomDetail",
|
||||||
"tr": "Sanal Sınıf",
|
"tr": "Sanal Sınıf",
|
||||||
"en": "Virtul Classroom"
|
"en": "Virtul Classroom"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Classroom.Planning",
|
"key": "App.Coordinator.Classroom.Planning",
|
||||||
"tr": "Sınıf Planlama",
|
"tr": "Sınıf Planlama",
|
||||||
"en": "Classroom Planning"
|
"en": "Classroom Planning"
|
||||||
},
|
},
|
||||||
|
|
@ -12797,41 +12809,42 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "admin.classroom.dashboard",
|
"key": "admin.coordinator.classroom.dashboard",
|
||||||
"path": "/admin/classroom/dashboard",
|
"path": "/admin/coordinator/classroom/dashboard",
|
||||||
"componentPath": "@/views/classroom/Dashboard",
|
"componentPath": "@/views/coordinator/Classroom/Dashboard",
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": [
|
"authority": [
|
||||||
"App.Classroom.Dashboard"
|
"App.Coordinator.Classroom.Dashboard"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "admin.classroom.classes",
|
"key": "admin.coordinator.classroom.classes",
|
||||||
"path": "/admin/classroom/classes",
|
"path": "/admin/coordinator/classroom/classes",
|
||||||
"componentPath": "@/views/classroom/ClassList",
|
"componentPath": "@/views/coordinator/Classroom/ClassList",
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": [
|
"authority": [
|
||||||
"App.Classroom.List"
|
"App.Coordinator.Classroom.List"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "admin.classroom.classroom",
|
"key": "admin.coordinator.classroom.classroom",
|
||||||
"path": "/admin/classroom/room/:id",
|
"path": "/admin/coordinator/classroom/room/:id",
|
||||||
"componentPath": "@/views/classroom/RoomDetail",
|
"componentPath": "@/views/coordinator/Classroom/RoomDetail",
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": [
|
"authority": [
|
||||||
"App.Classroom.RoomDetail"
|
"App.Coordinator.Classroom.RoomDetail"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "admin.classroom.planning",
|
"key": "admin.coordinator.classroom.planning",
|
||||||
"path": "/admin/classroom/planning/:id",
|
"path": "/admin/coordinator/classroom/planning/:id",
|
||||||
"componentPath": "@/views/classroom/PlanningPage",
|
"componentPath": "@/views/coordinator/Classroom/PlanningPage",
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": [
|
"authority": [
|
||||||
"App.Classroom.Planning"
|
"App.Coordinator.Classroom.Planning"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"key": "admin.supplychain.materialTypes",
|
"key": "admin.supplychain.materialTypes",
|
||||||
"path": "/admin/supplychain/materials/types",
|
"path": "/admin/supplychain/materials/types",
|
||||||
|
|
@ -14599,22 +14612,32 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ParentCode": "App.Coordinator.Definitions",
|
"ParentCode": "App.Coordinator.Definitions",
|
||||||
"Code": "App.Classroom.Tag",
|
"Code": "App.Definitions.Tag",
|
||||||
"DisplayName": "App.Classroom.Tag",
|
"DisplayName": "App.Definitions.Tag",
|
||||||
"Order": 10,
|
"Order": 10,
|
||||||
"Url": "/admin/list/list-tag",
|
"Url": "/admin/list/list-tag",
|
||||||
"Icon": "FcTags",
|
"Icon": "FcTags",
|
||||||
"RequiredPermissionName": "App.Classroom.Tag",
|
"RequiredPermissionName": "App.Definitions.Tag",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Coordinator.Definitions",
|
||||||
|
"Code": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "App.Definitions.QuestionPool",
|
||||||
|
"Order": 11,
|
||||||
|
"Url": "/admin/list/list-questionpool",
|
||||||
|
"Icon": "FcQuestions",
|
||||||
|
"RequiredPermissionName": "App.Definitions.QuestionPool",
|
||||||
"IsDisabled": false
|
"IsDisabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ParentCode": "App.Coordinator",
|
"ParentCode": "App.Coordinator",
|
||||||
"Code": "App.Classroom",
|
"Code": "App.Coordinator.Classroom",
|
||||||
"DisplayName": "App.Classroom",
|
"DisplayName": "App.Coordinator.Classroom",
|
||||||
"Order": 2,
|
"Order": 2,
|
||||||
"Url": "/admin/classroom/dashboard",
|
"Url": "/admin/coordinator/classroom/dashboard",
|
||||||
"Icon": "FcNeutralDecision",
|
"Icon": "FcNeutralDecision",
|
||||||
"RequiredPermissionName": "App.Classroom.Dashboard",
|
"RequiredPermissionName": "App.Coordinator.Classroom.Dashboard",
|
||||||
"IsDisabled": false
|
"IsDisabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -21895,62 +21918,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom",
|
"Name": "App.Definitions.Tag",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Classroom",
|
"DisplayName": "App.Definitions.Tag",
|
||||||
"IsEnabled": true,
|
|
||||||
"MultiTenancySide": 2,
|
|
||||||
"MenuGroup": "Kurs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"GroupName": "App.Coordinator",
|
|
||||||
"Name": "App.Classroom.Dashboard",
|
|
||||||
"ParentName": "App.Classroom",
|
|
||||||
"DisplayName": "App.Classroom.Dashboard",
|
|
||||||
"IsEnabled": true,
|
|
||||||
"MultiTenancySide": 2,
|
|
||||||
"MenuGroup": "Kurs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"GroupName": "App.Coordinator",
|
|
||||||
"Name": "App.Classroom.List",
|
|
||||||
"ParentName": "App.Classroom",
|
|
||||||
"DisplayName": "App.Classroom.List",
|
|
||||||
"IsEnabled": true,
|
|
||||||
"MultiTenancySide": 2,
|
|
||||||
"MenuGroup": "Kurs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"GroupName": "App.Coordinator",
|
|
||||||
"Name": "App.Classroom.RoomDetail",
|
|
||||||
"ParentName": "App.Classroom",
|
|
||||||
"DisplayName": "App.Classroom.RoomDetail",
|
|
||||||
"IsEnabled": true,
|
|
||||||
"MultiTenancySide": 2,
|
|
||||||
"MenuGroup": "Kurs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"GroupName": "App.Coordinator",
|
|
||||||
"Name": "App.Classroom.Planning",
|
|
||||||
"ParentName": "App.Classroom",
|
|
||||||
"DisplayName": "App.Classroom.Planning",
|
|
||||||
"IsEnabled": true,
|
|
||||||
"MultiTenancySide": 2,
|
|
||||||
"MenuGroup": "Kurs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"GroupName": "App.Coordinator",
|
|
||||||
"Name": "App.Classroom.Tag",
|
|
||||||
"ParentName": null,
|
|
||||||
"DisplayName": "App.Classroom.Tag",
|
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"MenuGroup": "Kurs"
|
"MenuGroup": "Kurs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom.Tag.Create",
|
"Name": "App.Definitions.Tag.Create",
|
||||||
"ParentName": "App.Classroom.Tag",
|
"ParentName": "App.Definitions.Tag",
|
||||||
"DisplayName": "Create",
|
"DisplayName": "Create",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -21958,8 +21936,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom.Tag.Update",
|
"Name": "App.Definitions.Tag.Update",
|
||||||
"ParentName": "App.Classroom.Tag",
|
"ParentName": "App.Definitions.Tag",
|
||||||
"DisplayName": "Update",
|
"DisplayName": "Update",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -21967,8 +21945,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom.Tag.Delete",
|
"Name": "App.Definitions.Tag.Delete",
|
||||||
"ParentName": "App.Classroom.Tag",
|
"ParentName": "App.Definitions.Tag",
|
||||||
"DisplayName": "Delete",
|
"DisplayName": "Delete",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -21976,8 +21954,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom.Tag.Export",
|
"Name": "App.Definitions.Tag.Export",
|
||||||
"ParentName": "App.Classroom.Tag",
|
"ParentName": "App.Definitions.Tag",
|
||||||
"DisplayName": "Export",
|
"DisplayName": "Export",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -21985,8 +21963,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom.Tag.Import",
|
"Name": "App.Definitions.Tag.Import",
|
||||||
"ParentName": "App.Classroom.Tag",
|
"ParentName": "App.Definitions.Tag",
|
||||||
"DisplayName": "Import",
|
"DisplayName": "Import",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -21994,13 +21972,185 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Coordinator",
|
"GroupName": "App.Coordinator",
|
||||||
"Name": "App.Classroom.Tag.Activity",
|
"Name": "App.Definitions.Tag.Activity",
|
||||||
"ParentName": "App.Classroom.Tag",
|
"ParentName": "App.Definitions.Tag",
|
||||||
"DisplayName": "Activity",
|
"DisplayName": "Activity",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"MenuGroup": "Kurs"
|
"MenuGroup": "Kurs"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Definitions.QuestionPool",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool.Create",
|
||||||
|
"ParentName": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "Create",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool.Update",
|
||||||
|
"ParentName": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "Update",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool.Delete",
|
||||||
|
"ParentName": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "Delete",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool.Export",
|
||||||
|
"ParentName": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "Export",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool.Import",
|
||||||
|
"ParentName": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "Import",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.QuestionPool.Activity",
|
||||||
|
"ParentName": "App.Definitions.QuestionPool",
|
||||||
|
"DisplayName": "Activity",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Definitions.Question",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question.Create",
|
||||||
|
"ParentName": "App.Definitions.Question",
|
||||||
|
"DisplayName": "Create",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question.Update",
|
||||||
|
"ParentName": "App.Definitions.Question",
|
||||||
|
"DisplayName": "Update",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question.Delete",
|
||||||
|
"ParentName": "App.Definitions.Question",
|
||||||
|
"DisplayName": "Delete",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question.Export",
|
||||||
|
"ParentName": "App.Definitions.Question",
|
||||||
|
"DisplayName": "Export",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question.Import",
|
||||||
|
"ParentName": "App.Definitions.Question",
|
||||||
|
"DisplayName": "Import",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Definitions.Question.Activity",
|
||||||
|
"ParentName": "App.Definitions.Question",
|
||||||
|
"DisplayName": "Activity",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 3,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Coordinator.Classroom",
|
||||||
|
"ParentName": null,
|
||||||
|
"DisplayName": "App.Coordinator.Classroom",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 2,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Coordinator.Classroom.Dashboard",
|
||||||
|
"ParentName": "App.Coordinator.Classroom",
|
||||||
|
"DisplayName": "App.Coordinator.Classroom.Dashboard",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 2,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Coordinator.Classroom.List",
|
||||||
|
"ParentName": "App.Coordinator.Classroom",
|
||||||
|
"DisplayName": "App.Coordinator.Classroom.List",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 2,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Coordinator.Classroom.RoomDetail",
|
||||||
|
"ParentName": "App.Coordinator.Classroom",
|
||||||
|
"DisplayName": "App.Coordinator.Classroom.RoomDetail",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 2,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GroupName": "App.Coordinator",
|
||||||
|
"Name": "App.Coordinator.Classroom.Planning",
|
||||||
|
"ParentName": "App.Coordinator.Classroom",
|
||||||
|
"DisplayName": "App.Coordinator.Classroom.Planning",
|
||||||
|
"IsEnabled": true,
|
||||||
|
"MultiTenancySide": 2,
|
||||||
|
"MenuGroup": "Kurs"
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"GroupName": "App.SupplyChain",
|
"GroupName": "App.SupplyChain",
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -149,6 +149,22 @@ public static class PlatformConsts
|
||||||
$"\"{SelectCommandByTableName("InstallmentOption", Prefix.DbTableWeb)}\".\"Name\" AS \"Name\" " +
|
$"\"{SelectCommandByTableName("InstallmentOption", Prefix.DbTableWeb)}\".\"Name\" AS \"Name\" " +
|
||||||
$"FROM \"{SelectCommandByTableName("InstallmentOption", Prefix.DbTableWeb)}\" " +
|
$"FROM \"{SelectCommandByTableName("InstallmentOption", Prefix.DbTableWeb)}\" " +
|
||||||
$"ORDER BY \"{SelectCommandByTableName("InstallmentOption", Prefix.DbTableWeb)}\".\"Installment\";";
|
$"ORDER BY \"{SelectCommandByTableName("InstallmentOption", Prefix.DbTableWeb)}\".\"Installment\";";
|
||||||
|
|
||||||
|
public static string QuestionPoolValues =
|
||||||
|
$"SELECT " +
|
||||||
|
$"\"Id\" AS \"Key\", " +
|
||||||
|
$"\"Name\" AS \"Name\" " +
|
||||||
|
$"FROM \"{SelectCommandByTableName("QuestionPool", Prefix.DbTableCoordinator)}\" " +
|
||||||
|
$"WHERE " +
|
||||||
|
$"\"IsDeleted\" = 'false' ";
|
||||||
|
|
||||||
|
public static string QuestionTagValues =
|
||||||
|
$"SELECT " +
|
||||||
|
$"\"Id\" AS \"Key\", " +
|
||||||
|
$"\"Name\" AS \"Name\" " +
|
||||||
|
$"FROM \"{SelectCommandByTableName("Tag", Prefix.DbTableCoordinator)}\" " +
|
||||||
|
$"WHERE " +
|
||||||
|
$"\"IsDeleted\" = 'false' ";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Prefix
|
public static class Prefix
|
||||||
|
|
@ -508,10 +524,11 @@ public static class PlatformConsts
|
||||||
{
|
{
|
||||||
public static class Forms
|
public static class Forms
|
||||||
{
|
{
|
||||||
public const string FormTenant = "form-tenant";
|
|
||||||
public const string FormLanguage = "form-language";
|
public const string FormLanguage = "form-language";
|
||||||
public const string FormUomCategory = "form-uomcategory";
|
public const string FormUomCategory = "form-uomcategory";
|
||||||
public const string FormSkillType = "form-skilltype";
|
public const string FormSkillType = "form-skilltype";
|
||||||
|
public const string FormTenant = "form-tenant";
|
||||||
|
public const string FormQuestionPool = "form-questionpool";
|
||||||
public const string FormBank = "form-bank";
|
public const string FormBank = "form-bank";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -596,6 +613,8 @@ public static class PlatformConsts
|
||||||
public const string Class = "list-class";
|
public const string Class = "list-class";
|
||||||
public const string Level = "list-level";
|
public const string Level = "list-level";
|
||||||
public const string Tag = "list-tag";
|
public const string Tag = "list-tag";
|
||||||
|
public const string QuestionPool = "list-questionpool";
|
||||||
|
public const string Question = "list-question";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -438,12 +438,14 @@ public static class SeedConsts
|
||||||
public const string ClassType = Default + ".ClassType";
|
public const string ClassType = Default + ".ClassType";
|
||||||
public const string Class = Default + ".Class";
|
public const string Class = Default + ".Class";
|
||||||
public const string Level = Default + ".Level";
|
public const string Level = Default + ".Level";
|
||||||
|
public const string Tag = Default + ".Tag";
|
||||||
|
public const string QuestionPool = Default + ".QuestionPool";
|
||||||
|
public const string Question = Default + ".Question";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Classroom
|
public static class Coordinator
|
||||||
{
|
{
|
||||||
public const string Default = Prefix.App + ".Classroom";
|
public const string Default = Prefix.App + ".Classroom";
|
||||||
public const string Tag = Default + ".Tag";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Accounting
|
public static class Accounting
|
||||||
|
|
|
||||||
32
api/src/Kurs.Platform.Domain/Entities/Tenant/Question.cs
Normal file
32
api/src/Kurs.Platform.Domain/Entities/Tenant/Question.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
||||||
|
public class Question : FullAuditedEntity<Guid>, IMultiTenant
|
||||||
|
{
|
||||||
|
public Guid? TenantId;
|
||||||
|
|
||||||
|
public string QuestionType { get; set; } // "multiple-choice", "fill-blank" vb.
|
||||||
|
public int Points { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
public string MediaUrl { get; set; }
|
||||||
|
public string MediaType { get; set; }
|
||||||
|
public string CorrectAnswer { get; set; }
|
||||||
|
public string Difficulty { get; set; } // "easy", "medium", "hard"
|
||||||
|
public int TimeLimit { get; set; }
|
||||||
|
public string Explanation { get; set; }
|
||||||
|
|
||||||
|
public ICollection<QuestionOption> Options { get; set; } = [];
|
||||||
|
|
||||||
|
// Foreign key
|
||||||
|
public Guid QuestionPoolId { get; set; }
|
||||||
|
public QuestionPool QuestionPool { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
Guid? IMultiTenant.TenantId => TenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
||||||
|
public class QuestionOption : FullAuditedEntity<Guid>, IMultiTenant
|
||||||
|
{
|
||||||
|
public Guid? TenantId;
|
||||||
|
|
||||||
|
public string Text { get; set; }
|
||||||
|
public bool IsCorrect { get; set; }
|
||||||
|
|
||||||
|
// Foreign key
|
||||||
|
public Guid QuestionId { get; set; }
|
||||||
|
public Question Question { get; set; }
|
||||||
|
|
||||||
|
Guid? IMultiTenant.TenantId => TenantId;
|
||||||
|
}
|
||||||
19
api/src/Kurs.Platform.Domain/Entities/Tenant/QuestionPool.cs
Normal file
19
api/src/Kurs.Platform.Domain/Entities/Tenant/QuestionPool.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
namespace Kurs.Platform.Entities;
|
||||||
|
|
||||||
|
public class QuestionPool : FullAuditedEntity<Guid>, IMultiTenant
|
||||||
|
{
|
||||||
|
public Guid? TenantId;
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string Tags { get; set; } // İstersen JSON veya ayrı tablo da olabilir
|
||||||
|
|
||||||
|
public ICollection<Question> Questions { get; set; } = new List<Question>();
|
||||||
|
|
||||||
|
Guid? IMultiTenant.TenantId => TenantId;
|
||||||
|
}
|
||||||
|
|
@ -141,6 +141,9 @@ public class PlatformDbContext :
|
||||||
public DbSet<ClassroomChat> ChatMessages { get; set; }
|
public DbSet<ClassroomChat> ChatMessages { get; set; }
|
||||||
|
|
||||||
public DbSet<Tag> Tags { get; set; }
|
public DbSet<Tag> Tags { get; set; }
|
||||||
|
public DbSet<QuestionPool> QuestionPools { get; set; }
|
||||||
|
public DbSet<Question> Questions { get; set; }
|
||||||
|
public DbSet<QuestionOption> QuestionOptions { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
@ -488,6 +491,16 @@ public class PlatformDbContext :
|
||||||
b.Property(x => x.ErrorsJson).HasColumnType("text");
|
b.Property(x => x.ErrorsJson).HasColumnType("text");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Entity<Activity>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(Prefix.DbTableDefault + nameof(Activity), Prefix.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(x => x.Type).IsRequired();
|
||||||
|
b.Property(x => x.Subject).IsRequired().HasMaxLength(256);
|
||||||
|
b.Property(x => x.Content).IsRequired().HasMaxLength(2000);
|
||||||
|
});
|
||||||
|
|
||||||
builder.Entity<BackgroundWorker>(b =>
|
builder.Entity<BackgroundWorker>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(Prefix.DbTableDefault + nameof(BackgroundWorker), Prefix.DbSchema);
|
b.ToTable(Prefix.DbTableDefault + nameof(BackgroundWorker), Prefix.DbSchema);
|
||||||
|
|
@ -1487,7 +1500,7 @@ public class PlatformDbContext :
|
||||||
//Coordinator
|
//Coordinator
|
||||||
builder.Entity<Classroom>(b =>
|
builder.Entity<Classroom>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(Prefix.DbTableDefault + nameof(Classroom), Prefix.DbSchema);
|
b.ToTable(Prefix.DbTableCoordinator + nameof(Classroom), Prefix.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.Name).IsRequired().HasMaxLength(200);
|
b.Property(x => x.Name).IsRequired().HasMaxLength(200);
|
||||||
|
|
@ -1516,7 +1529,7 @@ public class PlatformDbContext :
|
||||||
|
|
||||||
builder.Entity<ClassroomParticipant>(b =>
|
builder.Entity<ClassroomParticipant>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(Prefix.DbTableDefault + nameof(ClassroomParticipant), Prefix.DbSchema);
|
b.ToTable(Prefix.DbTableCoordinator + nameof(ClassroomParticipant), Prefix.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.UserName).IsRequired().HasMaxLength(100);
|
b.Property(x => x.UserName).IsRequired().HasMaxLength(100);
|
||||||
|
|
@ -1531,7 +1544,7 @@ public class PlatformDbContext :
|
||||||
|
|
||||||
builder.Entity<ClassroomAttandance>(b =>
|
builder.Entity<ClassroomAttandance>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(Prefix.DbTableDefault + nameof(ClassroomAttandance), Prefix.DbSchema);
|
b.ToTable(Prefix.DbTableCoordinator + nameof(ClassroomAttandance), Prefix.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.StudentName).IsRequired().HasMaxLength(100);
|
b.Property(x => x.StudentName).IsRequired().HasMaxLength(100);
|
||||||
|
|
@ -1543,7 +1556,7 @@ public class PlatformDbContext :
|
||||||
|
|
||||||
builder.Entity<ClassroomChat>(b =>
|
builder.Entity<ClassroomChat>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(Prefix.DbTableDefault + nameof(ClassroomChat), Prefix.DbSchema);
|
b.ToTable(Prefix.DbTableCoordinator + nameof(ClassroomChat), Prefix.DbSchema);
|
||||||
b.ConfigureByConvention();
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
b.Property(x => x.SenderName).IsRequired().HasMaxLength(100);
|
b.Property(x => x.SenderName).IsRequired().HasMaxLength(100);
|
||||||
|
|
@ -1554,18 +1567,6 @@ public class PlatformDbContext :
|
||||||
b.HasIndex(x => x.Timestamp);
|
b.HasIndex(x => x.Timestamp);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form Activity Entities
|
|
||||||
builder.Entity<Activity>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(Prefix.DbTableDefault + nameof(Activity), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.Type).IsRequired();
|
|
||||||
b.Property(x => x.Subject).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.Content).IsRequired().HasMaxLength(2000);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Classroom
|
|
||||||
builder.Entity<Tag>(b =>
|
builder.Entity<Tag>(b =>
|
||||||
{
|
{
|
||||||
b.ToTable(Prefix.DbTableCoordinator + nameof(Tag), Prefix.DbSchema);
|
b.ToTable(Prefix.DbTableCoordinator + nameof(Tag), Prefix.DbSchema);
|
||||||
|
|
@ -1576,5 +1577,41 @@ public class PlatformDbContext :
|
||||||
b.Property(x => x.Color).HasMaxLength(7);
|
b.Property(x => x.Color).HasMaxLength(7);
|
||||||
b.Property(x => x.UsageCount).HasDefaultValue(0);
|
b.Property(x => x.UsageCount).HasDefaultValue(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Entity<QuestionPool>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(Prefix.DbTableCoordinator + nameof(QuestionPool), Prefix.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(x => x.Name).IsRequired().HasMaxLength(100);
|
||||||
|
b.Property(x => x.Description).HasMaxLength(500);
|
||||||
|
b.Property(x => x.Tags).HasMaxLength(500);
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Entity<Question>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(Prefix.DbTableCoordinator + nameof(Question), Prefix.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(x => x.QuestionType).IsRequired().HasMaxLength(100);
|
||||||
|
b.Property(x => x.Points).HasDefaultValue(0);
|
||||||
|
b.Property(x => x.Title).IsRequired().HasMaxLength(500);
|
||||||
|
b.Property(x => x.Content).HasMaxLength(500);
|
||||||
|
b.Property(x => x.MediaUrl).HasMaxLength(500);
|
||||||
|
b.Property(x => x.MediaType).HasMaxLength(500);
|
||||||
|
b.Property(x => x.CorrectAnswer).HasMaxLength(50);
|
||||||
|
b.Property(x => x.Difficulty).HasMaxLength(10);
|
||||||
|
b.Property(x => x.TimeLimit).HasDefaultValue(0);
|
||||||
|
b.Property(x => x.Explanation).HasMaxLength(500);
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Entity<QuestionOption>(b =>
|
||||||
|
{
|
||||||
|
b.ToTable(Prefix.DbTableCoordinator + nameof(QuestionOption), Prefix.DbSchema);
|
||||||
|
b.ConfigureByConvention();
|
||||||
|
|
||||||
|
b.Property(x => x.Text).HasMaxLength(100);
|
||||||
|
b.Property(x => x.IsCorrect).HasDefaultValue(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Kurs.Platform.Migrations
|
namespace Kurs.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20251015192202_Initial")]
|
[Migration("20251016120353_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -1780,7 +1780,7 @@ namespace Kurs.Platform.Migrations
|
||||||
|
|
||||||
b.HasIndex("TeacherId");
|
b.HasIndex("TeacherId");
|
||||||
|
|
||||||
b.ToTable("PClassroom", (string)null);
|
b.ToTable("CClassroom", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
||||||
|
|
@ -1853,7 +1853,7 @@ namespace Kurs.Platform.Migrations
|
||||||
|
|
||||||
b.HasIndex("StudentId");
|
b.HasIndex("StudentId");
|
||||||
|
|
||||||
b.ToTable("PClassroomAttandance", (string)null);
|
b.ToTable("CClassroomAttandance", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
||||||
|
|
@ -1937,7 +1937,7 @@ namespace Kurs.Platform.Migrations
|
||||||
|
|
||||||
b.HasIndex("Timestamp");
|
b.HasIndex("Timestamp");
|
||||||
|
|
||||||
b.ToTable("PClassroomChat", (string)null);
|
b.ToTable("CClassroomChat", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
||||||
|
|
@ -2032,7 +2032,7 @@ namespace Kurs.Platform.Migrations
|
||||||
.IsUnique()
|
.IsUnique()
|
||||||
.HasFilter("[UserId] IS NOT NULL");
|
.HasFilter("[UserId] IS NOT NULL");
|
||||||
|
|
||||||
b.ToTable("PClassroomParticipant", (string)null);
|
b.ToTable("CClassroomParticipant", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
||||||
|
|
@ -5103,6 +5103,214 @@ namespace Kurs.Platform.Migrations
|
||||||
b.ToTable("DPsychologist", (string)null);
|
b.ToTable("DPsychologist", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<string>("CorrectAnswer")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("nvarchar(50)");
|
||||||
|
|
||||||
|
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<string>("Difficulty")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("nvarchar(10)");
|
||||||
|
|
||||||
|
b.Property<string>("Explanation")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("MediaType")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<string>("MediaUrl")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<int>("Points")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<Guid>("QuestionPoolId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("QuestionType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.Property<int>("TimeLimit")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionPoolId");
|
||||||
|
|
||||||
|
b.ToTable("CQuestion", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionOption", 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>("IsCorrect")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<Guid>("QuestionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("CQuestionOption", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionPool", 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<string>("Description")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<string>("Tags")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CQuestionPool", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -6115,7 +6323,6 @@ namespace Kurs.Platform.Migrations
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Tag", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Tag", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
b.Property<string>("Color")
|
b.Property<string>("Color")
|
||||||
|
|
@ -8969,6 +9176,28 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Order");
|
b.Navigation("Order");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Kurs.Platform.Entities.QuestionPool", "QuestionPool")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionPoolId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("QuestionPool");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionOption", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Kurs.Platform.Entities.Question", "Question")
|
||||||
|
.WithMany("Options")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.RegistrationType", "RegistrationType")
|
b.HasOne("Kurs.Platform.Entities.RegistrationType", "RegistrationType")
|
||||||
|
|
@ -9298,6 +9527,16 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Items");
|
b.Navigation("Items");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Options");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionPool", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationType", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationType", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("ClassTypes");
|
b.Navigation("ClassTypes");
|
||||||
|
|
@ -434,6 +434,61 @@ namespace Kurs.Platform.Migrations
|
||||||
table.PrimaryKey("PK_AbpUsers", x => x.Id);
|
table.PrimaryKey("PK_AbpUsers", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CClassroom",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
||||||
|
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
||||||
|
Subject = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||||
|
TeacherId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
TeacherName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
ScheduledStartTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
ScheduledEndTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
Duration = table.Column<int>(type: "int", nullable: false),
|
||||||
|
ActualStartTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
ActualEndTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
MaxParticipants = table.Column<int>(type: "int", nullable: false),
|
||||||
|
ParticipantCount = table.Column<int>(type: "int", nullable: false),
|
||||||
|
SettingsJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CClassroom", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CQuestionPool",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
Description = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||||
|
Tags = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CQuestionPool", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "CTag",
|
name: "CTag",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -1370,39 +1425,6 @@ namespace Kurs.Platform.Migrations
|
||||||
table.PrimaryKey("PK_PBranchUsers", x => new { x.UserId, x.BranchId });
|
table.PrimaryKey("PK_PBranchUsers", x => new { x.UserId, x.BranchId });
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PClassroom",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
|
|
||||||
Description = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true),
|
|
||||||
Subject = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
|
||||||
TeacherId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
TeacherName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
|
||||||
ScheduledStartTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
ScheduledEndTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
Duration = table.Column<int>(type: "int", nullable: false),
|
|
||||||
ActualStartTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
ActualEndTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
MaxParticipants = table.Column<int>(type: "int", nullable: false),
|
|
||||||
ParticipantCount = table.Column<int>(type: "int", nullable: false),
|
|
||||||
SettingsJson = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PClassroom", x => x.Id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "PCustomComponent",
|
name: "PCustomComponent",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -2325,6 +2347,146 @@ namespace Kurs.Platform.Migrations
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CClassroomAttandance",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
StudentId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
StudentName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
JoinTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
LeaveTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
TotalDurationMinutes = table.Column<int>(type: "int", nullable: false),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CClassroomAttandance", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_CClassroomAttandance_CClassroom_SessionId",
|
||||||
|
column: x => x.SessionId,
|
||||||
|
principalTable: "CClassroom",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CClassroomChat",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
SenderId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
SenderName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
Message = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, 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),
|
||||||
|
MessageType = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CClassroomChat", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_CClassroomChat_CClassroom_SessionId",
|
||||||
|
column: x => x.SessionId,
|
||||||
|
principalTable: "CClassroom",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CClassroomParticipant",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
UserName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
IsTeacher = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsAudioMuted = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsVideoMuted = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsHandRaised = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsKicked = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
||||||
|
JoinTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
ConnectionId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CClassroomParticipant", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_CClassroomParticipant_CClassroom_SessionId",
|
||||||
|
column: x => x.SessionId,
|
||||||
|
principalTable: "CClassroom",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CQuestion",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
QuestionType = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
Points = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
|
||||||
|
Title = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false),
|
||||||
|
Content = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||||
|
MediaUrl = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||||
|
MediaType = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||||
|
CorrectAnswer = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
|
||||||
|
Difficulty = table.Column<string>(type: "nvarchar(10)", maxLength: 10, nullable: true),
|
||||||
|
TimeLimit = table.Column<int>(type: "int", nullable: false, defaultValue: 0),
|
||||||
|
Explanation = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true),
|
||||||
|
QuestionPoolId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CQuestion", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_CQuestion_CQuestionPool_QuestionPoolId",
|
||||||
|
column: x => x.QuestionPoolId,
|
||||||
|
principalTable: "CQuestionPool",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "DCountry",
|
name: "DCountry",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -2674,110 +2836,6 @@ namespace Kurs.Platform.Migrations
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PClassroomAttandance",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
StudentId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
StudentName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
|
||||||
JoinTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
LeaveTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
TotalDurationMinutes = table.Column<int>(type: "int", nullable: false),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PClassroomAttandance", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PClassroomAttandance_PClassroom_SessionId",
|
|
||||||
column: x => x.SessionId,
|
|
||||||
principalTable: "PClassroom",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PClassroomChat",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
SenderId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
SenderName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
|
||||||
Message = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, 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),
|
|
||||||
MessageType = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PClassroomChat", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PClassroomChat_PClassroom_SessionId",
|
|
||||||
column: x => x.SessionId,
|
|
||||||
principalTable: "PClassroom",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PClassroomParticipant",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
BranchId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
SessionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
UserName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
|
||||||
IsTeacher = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
IsAudioMuted = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
IsVideoMuted = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
IsHandRaised = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
IsKicked = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
|
|
||||||
JoinTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
ConnectionId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
|
||||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
|
||||||
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PClassroomParticipant", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PClassroomParticipant_PClassroom_SessionId",
|
|
||||||
column: x => x.SessionId,
|
|
||||||
principalTable: "PClassroom",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "PApiEndpoint",
|
name: "PApiEndpoint",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -3215,6 +3273,34 @@ namespace Kurs.Platform.Migrations
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CQuestionOption",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
Text = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
|
||||||
|
IsCorrect = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
QuestionId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
|
||||||
|
DeleterId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CQuestionOption", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_CQuestionOption_CQuestion_QuestionId",
|
||||||
|
column: x => x.QuestionId,
|
||||||
|
principalTable: "CQuestion",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "DCity",
|
name: "DCity",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -3748,6 +3834,73 @@ namespace Kurs.Platform.Migrations
|
||||||
table: "AbpUsers",
|
table: "AbpUsers",
|
||||||
column: "UserName");
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroom_ScheduledStartTime",
|
||||||
|
table: "CClassroom",
|
||||||
|
column: "ScheduledStartTime");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroom_TeacherId",
|
||||||
|
table: "CClassroom",
|
||||||
|
column: "TeacherId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomAttandance_JoinTime",
|
||||||
|
table: "CClassroomAttandance",
|
||||||
|
column: "JoinTime");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomAttandance_SessionId",
|
||||||
|
table: "CClassroomAttandance",
|
||||||
|
column: "SessionId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomAttandance_StudentId",
|
||||||
|
table: "CClassroomAttandance",
|
||||||
|
column: "StudentId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomChat_SenderId",
|
||||||
|
table: "CClassroomChat",
|
||||||
|
column: "SenderId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomChat_SessionId",
|
||||||
|
table: "CClassroomChat",
|
||||||
|
column: "SessionId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomChat_Timestamp",
|
||||||
|
table: "CClassroomChat",
|
||||||
|
column: "Timestamp");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomParticipant_SessionId",
|
||||||
|
table: "CClassroomParticipant",
|
||||||
|
column: "SessionId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomParticipant_SessionId_UserId",
|
||||||
|
table: "CClassroomParticipant",
|
||||||
|
columns: new[] { "SessionId", "UserId" },
|
||||||
|
unique: true,
|
||||||
|
filter: "[UserId] IS NOT NULL");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CClassroomParticipant_UserId",
|
||||||
|
table: "CClassroomParticipant",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CQuestion_QuestionPoolId",
|
||||||
|
table: "CQuestion",
|
||||||
|
column: "QuestionPoolId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_CQuestionOption_QuestionId",
|
||||||
|
table: "CQuestionOption",
|
||||||
|
column: "QuestionId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_DBankAccount_BankId",
|
name: "IX_DBankAccount_BankId",
|
||||||
table: "DBankAccount",
|
table: "DBankAccount",
|
||||||
|
|
@ -3905,63 +4058,6 @@ namespace Kurs.Platform.Migrations
|
||||||
columns: new[] { "TableName", "Order" },
|
columns: new[] { "TableName", "Order" },
|
||||||
unique: true);
|
unique: true);
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassroom_ScheduledStartTime",
|
|
||||||
table: "PClassroom",
|
|
||||||
column: "ScheduledStartTime");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_PClassroom_TeacherId",
|
|
||||||
table: "PClassroom",
|
|
||||||
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_PCustomEntityField_EntityId",
|
name: "IX_PCustomEntityField_EntityId",
|
||||||
table: "PCustomEntityField",
|
table: "PCustomEntityField",
|
||||||
|
|
@ -4165,6 +4261,18 @@ namespace Kurs.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "AbpUserTokens");
|
name: "AbpUserTokens");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CClassroomAttandance");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CClassroomChat");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CClassroomParticipant");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CQuestionOption");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "CTag");
|
name: "CTag");
|
||||||
|
|
||||||
|
|
@ -4294,15 +4402,6 @@ namespace Kurs.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PBranchUsers");
|
name: "PBranchUsers");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PClassroomAttandance");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PClassroomChat");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PClassroomParticipant");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PCustomComponent");
|
name: "PCustomComponent");
|
||||||
|
|
||||||
|
|
@ -4396,6 +4495,12 @@ namespace Kurs.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "AbpUsers");
|
name: "AbpUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CClassroom");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CQuestion");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "DBank");
|
name: "DBank");
|
||||||
|
|
||||||
|
|
@ -4429,9 +4534,6 @@ namespace Kurs.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PBackgroundWorker_MailQueue");
|
name: "PBackgroundWorker_MailQueue");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "PClassroom");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PCustomEntity");
|
name: "PCustomEntity");
|
||||||
|
|
||||||
|
|
@ -4462,6 +4564,9 @@ namespace Kurs.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "AbpAuditLogs");
|
name: "AbpAuditLogs");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CQuestionPool");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "DCountry");
|
name: "DCountry");
|
||||||
|
|
||||||
|
|
@ -1777,7 +1777,7 @@ namespace Kurs.Platform.Migrations
|
||||||
|
|
||||||
b.HasIndex("TeacherId");
|
b.HasIndex("TeacherId");
|
||||||
|
|
||||||
b.ToTable("PClassroom", (string)null);
|
b.ToTable("CClassroom", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomAttandance", b =>
|
||||||
|
|
@ -1850,7 +1850,7 @@ namespace Kurs.Platform.Migrations
|
||||||
|
|
||||||
b.HasIndex("StudentId");
|
b.HasIndex("StudentId");
|
||||||
|
|
||||||
b.ToTable("PClassroomAttandance", (string)null);
|
b.ToTable("CClassroomAttandance", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomChat", b =>
|
||||||
|
|
@ -1934,7 +1934,7 @@ namespace Kurs.Platform.Migrations
|
||||||
|
|
||||||
b.HasIndex("Timestamp");
|
b.HasIndex("Timestamp");
|
||||||
|
|
||||||
b.ToTable("PClassroomChat", (string)null);
|
b.ToTable("CClassroomChat", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.ClassroomParticipant", b =>
|
||||||
|
|
@ -2029,7 +2029,7 @@ namespace Kurs.Platform.Migrations
|
||||||
.IsUnique()
|
.IsUnique()
|
||||||
.HasFilter("[UserId] IS NOT NULL");
|
.HasFilter("[UserId] IS NOT NULL");
|
||||||
|
|
||||||
b.ToTable("PClassroomParticipant", (string)null);
|
b.ToTable("CClassroomParticipant", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Contact", b =>
|
||||||
|
|
@ -5100,6 +5100,214 @@ namespace Kurs.Platform.Migrations
|
||||||
b.ToTable("DPsychologist", (string)null);
|
b.ToTable("DPsychologist", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<string>("CorrectAnswer")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("nvarchar(50)");
|
||||||
|
|
||||||
|
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<string>("Difficulty")
|
||||||
|
.HasMaxLength(10)
|
||||||
|
.HasColumnType("nvarchar(10)");
|
||||||
|
|
||||||
|
b.Property<string>("Explanation")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("MediaType")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<string>("MediaUrl")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<int>("Points")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<Guid>("QuestionPoolId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("QuestionType")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.Property<int>("TimeLimit")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasDefaultValue(0);
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionPoolId");
|
||||||
|
|
||||||
|
b.ToTable("CQuestion", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionOption", 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>("IsCorrect")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<Guid>("QuestionId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("CQuestionOption", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionPool", 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<string>("Description")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDeleted")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bit")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("IsDeleted");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2")
|
||||||
|
.HasColumnName("LastModificationTime");
|
||||||
|
|
||||||
|
b.Property<Guid?>("LastModifierId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("LastModifierId");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<string>("Tags")
|
||||||
|
.HasMaxLength(500)
|
||||||
|
.HasColumnType("nvarchar(500)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("TenantId")
|
||||||
|
.HasColumnType("uniqueidentifier")
|
||||||
|
.HasColumnName("TenantId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CQuestionPool", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -6112,7 +6320,6 @@ namespace Kurs.Platform.Migrations
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.Tag", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.Tag", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uniqueidentifier");
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
b.Property<string>("Color")
|
b.Property<string>("Color")
|
||||||
|
|
@ -8966,6 +9173,28 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Order");
|
b.Navigation("Order");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Kurs.Platform.Entities.QuestionPool", "QuestionPool")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionPoolId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("QuestionPool");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionOption", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Kurs.Platform.Entities.Question", "Question")
|
||||||
|
.WithMany("Options")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationMethod", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Kurs.Platform.Entities.RegistrationType", "RegistrationType")
|
b.HasOne("Kurs.Platform.Entities.RegistrationType", "RegistrationType")
|
||||||
|
|
@ -9295,6 +9524,16 @@ namespace Kurs.Platform.Migrations
|
||||||
b.Navigation("Items");
|
b.Navigation("Items");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Options");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Kurs.Platform.Entities.QuestionPool", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationType", b =>
|
modelBuilder.Entity("Kurs.Platform.Entities.RegistrationType", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("ClassTypes");
|
b.Navigation("ClassTypes");
|
||||||
|
|
|
||||||
|
|
@ -1827,6 +1827,61 @@
|
||||||
"Name": "Writing",
|
"Name": "Writing",
|
||||||
"Description": "Writing skills development",
|
"Description": "Writing skills development",
|
||||||
"Color": "#EF4444"
|
"Color": "#EF4444"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Verbs",
|
||||||
|
"Description": "Verbs and their usage",
|
||||||
|
"Color": "#EA580C"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"QuestionPools": [
|
||||||
|
{
|
||||||
|
"Name": "Grammar Fundamentals",
|
||||||
|
"Description": "Essential grammar concepts and structures",
|
||||||
|
"Tags": "Grammar|Verbs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Vocabulary Expansion",
|
||||||
|
"Description": "Exercises to enhance vocabulary",
|
||||||
|
"Tags": "Vocabulary|Reading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Reading Comprehension",
|
||||||
|
"Description": "Passages and questions to improve reading skills",
|
||||||
|
"Tags": "Reading|Verbs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Writing Practice",
|
||||||
|
"Description": "Prompts and exercises for writing improvement",
|
||||||
|
"Tags": "Writing"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Questions": [
|
||||||
|
{
|
||||||
|
"QuestionPoolName": "Grammar Fundamentals",
|
||||||
|
"QuestionType": "multiple-choice",
|
||||||
|
"Points": 10,
|
||||||
|
"Title": "Verb Tenses",
|
||||||
|
"Content": "Select the appropriate tense form for the given context.",
|
||||||
|
"MediaType": "image",
|
||||||
|
"MediaUrl": "",
|
||||||
|
"CorrectAnswer": "opt2",
|
||||||
|
"Difficulty": "easy",
|
||||||
|
"TimeLimit": 0,
|
||||||
|
"Explanation": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"QuestionPoolName": "Grammar Fundamentals",
|
||||||
|
"QuestionType": "fill-blank",
|
||||||
|
"Points": 15,
|
||||||
|
"Title": "Articles",
|
||||||
|
"Content": "Fill in the blank: \"I saw _____ elephant at the zoo yesterday.\"",
|
||||||
|
"MediaType": "image",
|
||||||
|
"MediaUrl": "",
|
||||||
|
"CorrectAnswer": "an",
|
||||||
|
"Difficulty": "medium",
|
||||||
|
"TimeLimit": 0,
|
||||||
|
"Explanation": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ using Volo.Abp.Data;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
using Volo.Abp.Domain.Repositories;
|
using Volo.Abp.Domain.Repositories;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Kurs.Platform.Data.Seeds;
|
namespace Kurs.Platform.Data.Seeds;
|
||||||
|
|
||||||
|
|
@ -53,6 +55,8 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
private readonly IRepository<WorkHour, Guid> _workHourRepository;
|
private readonly IRepository<WorkHour, Guid> _workHourRepository;
|
||||||
private readonly IRepository<Classroom, Guid> _classroomRepository;
|
private readonly IRepository<Classroom, Guid> _classroomRepository;
|
||||||
private readonly IRepository<Tag, Guid> _tagRepository;
|
private readonly IRepository<Tag, Guid> _tagRepository;
|
||||||
|
private readonly IRepository<QuestionPool, Guid> _questionPoolRepository;
|
||||||
|
private readonly IRepository<Question, Guid> _questionRepository;
|
||||||
|
|
||||||
public TenantDataSeeder(
|
public TenantDataSeeder(
|
||||||
IRepository<GlobalSearch, int> globalSearch,
|
IRepository<GlobalSearch, int> globalSearch,
|
||||||
|
|
@ -92,7 +96,9 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
IRepository<Interesting, Guid> interestingRepository,
|
IRepository<Interesting, Guid> interestingRepository,
|
||||||
IRepository<Program, Guid> programRepository,
|
IRepository<Program, Guid> programRepository,
|
||||||
IRepository<ForumCategory, Guid> forumCategoryRepository,
|
IRepository<ForumCategory, Guid> forumCategoryRepository,
|
||||||
IRepository<Tag, Guid> tagRepository
|
IRepository<Tag, Guid> tagRepository,
|
||||||
|
IRepository<QuestionPool, Guid> questionPoolRepository,
|
||||||
|
IRepository<Question, Guid> questionRepository
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_globalSearch = globalSearch;
|
_globalSearch = globalSearch;
|
||||||
|
|
@ -133,6 +139,8 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
_programRepository = programRepository;
|
_programRepository = programRepository;
|
||||||
_forumCategoryRepository = forumCategoryRepository;
|
_forumCategoryRepository = forumCategoryRepository;
|
||||||
_tagRepository = tagRepository;
|
_tagRepository = tagRepository;
|
||||||
|
_questionPoolRepository = questionPoolRepository;
|
||||||
|
_questionRepository = questionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IConfigurationRoot BuildConfiguration()
|
private static IConfigurationRoot BuildConfiguration()
|
||||||
|
|
@ -743,5 +751,74 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var item in items.QuestionPools)
|
||||||
|
{
|
||||||
|
var exists = await _questionPoolRepository.AnyAsync(x => x.Name == item.Name);
|
||||||
|
if (exists)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var tagNames = item.Tags.Split(PlatformConsts.MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(x => x.Trim())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var tagIds = new List<Guid>();
|
||||||
|
foreach (var tagName in tagNames)
|
||||||
|
{
|
||||||
|
var tagEntity = items.Tags.FirstOrDefault(t =>
|
||||||
|
string.Equals(t.Name, tagName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
if (tagEntity != null)
|
||||||
|
{
|
||||||
|
var existingTag = await _tagRepository.FirstOrDefaultAsync(x => x.Name == tagEntity.Name);
|
||||||
|
if (existingTag == null)
|
||||||
|
{
|
||||||
|
existingTag = await _tagRepository.InsertAsync(new Tag
|
||||||
|
{
|
||||||
|
Name = tagEntity.Name,
|
||||||
|
Description = tagEntity.Description,
|
||||||
|
Color = tagEntity.Color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
tagIds.Add(existingTag.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagIdString = string.Join(PlatformConsts.MultiValueDelimiter, tagIds);
|
||||||
|
await _questionPoolRepository.InsertAsync(new QuestionPool
|
||||||
|
{
|
||||||
|
Name = item.Name,
|
||||||
|
Description = item.Description,
|
||||||
|
Tags = tagIdString
|
||||||
|
}, autoSave: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in items.Questions)
|
||||||
|
{
|
||||||
|
var exists = await _questionRepository.AnyAsync(x => x.Title == item.Title);
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
var questionPool = await _questionPoolRepository.FirstOrDefaultAsync(x => x.Name == item.QuestionPoolName);
|
||||||
|
if (questionPool != null)
|
||||||
|
{
|
||||||
|
await _questionRepository.InsertAsync(new Question
|
||||||
|
{
|
||||||
|
QuestionPoolId = questionPool.Id,
|
||||||
|
Title = item.Title,
|
||||||
|
QuestionType = item.QuestionType,
|
||||||
|
Points = item.Points,
|
||||||
|
Content = item.Content,
|
||||||
|
MediaUrl = item.MediaUrl,
|
||||||
|
MediaType = item.MediaType,
|
||||||
|
CorrectAnswer = item.CorrectAnswer,
|
||||||
|
Difficulty = item.Difficulty,
|
||||||
|
TimeLimit = item.TimeLimit,
|
||||||
|
Explanation = item.Explanation
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ public class TenantSeederDto
|
||||||
public List<ContactSeedDto> Contacts { get; set; }
|
public List<ContactSeedDto> Contacts { get; set; }
|
||||||
public List<ClassroomSeedDto> Classrooms { get; set; }
|
public List<ClassroomSeedDto> Classrooms { get; set; }
|
||||||
public List<TagSeedDto> Tags { get; set; }
|
public List<TagSeedDto> Tags { get; set; }
|
||||||
|
public List<QuestionPoolSeedDto> QuestionPools { get; set; }
|
||||||
|
public List<QuestionSeedDto> Questions { get; set; }
|
||||||
|
|
||||||
//Tanımlamalar
|
//Tanımlamalar
|
||||||
public List<SectorSeedDto> Sectors { get; set; }
|
public List<SectorSeedDto> Sectors { get; set; }
|
||||||
|
|
@ -352,3 +354,25 @@ public class TagSeedDto
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string Color { get; set; }
|
public string Color { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class QuestionPoolSeedDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string Tags { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QuestionSeedDto
|
||||||
|
{
|
||||||
|
public string QuestionPoolName { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string QuestionType { get; set; }
|
||||||
|
public int Points { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
public string MediaUrl { get; set; }
|
||||||
|
public string MediaType { get; set; }
|
||||||
|
public string CorrectAnswer { get; set; }
|
||||||
|
public string Difficulty { get; set; }
|
||||||
|
public int TimeLimit { get; set; }
|
||||||
|
public string Explanation { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { QuestionPool } from "@/types/coordinator";
|
import { QuestionPoolDto } from "@/types/coordinator";
|
||||||
|
|
||||||
// Dynamic data - no hardcoded content
|
// Dynamic data - no hardcoded content
|
||||||
export const generateMockPools = (): QuestionPool[] => [
|
export const generateMockPools = (): QuestionPoolDto[] => [
|
||||||
{
|
{
|
||||||
id: "pool-1",
|
id: "pool-1",
|
||||||
name: "Grammar Fundamentals",
|
name: "Grammar Fundamentals",
|
||||||
|
|
|
||||||
|
|
@ -73,13 +73,19 @@ export const ROUTES_ENUM = {
|
||||||
formEdit: '/admin/form/:listFormCode/:id/edit',
|
formEdit: '/admin/form/:listFormCode/:id/edit',
|
||||||
chart: '/admin/chart/:listFormCode',
|
chart: '/admin/chart/:listFormCode',
|
||||||
pivot: '/admin/pivot/:listFormCode',
|
pivot: '/admin/pivot/:listFormCode',
|
||||||
|
},
|
||||||
|
|
||||||
|
participant: {},
|
||||||
|
|
||||||
|
coordinator: {
|
||||||
classroom: {
|
classroom: {
|
||||||
dashboard: '/admin/classroom/dashboard',
|
dashboard: '/admin/coordinator/classroom/dashboard',
|
||||||
classes: '/admin/classroom/classes',
|
classes: '/admin/coordinator/classroom/classes',
|
||||||
roomDetail: '/admin/classroom/room/:id',
|
roomDetail: '/admin/coordinator/classroom/room/:id',
|
||||||
planning: '/admin/classroom/planning/:id',
|
planning: '/admin/coordinator/classroom/planning/:id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
supplychain: {
|
supplychain: {
|
||||||
materialTypes: '/admin/supplychain/materials/types',
|
materialTypes: '/admin/supplychain/materials/types',
|
||||||
materialGroups: '/admin/supplychain/materials/groups',
|
materialGroups: '/admin/supplychain/materials/groups',
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ export class SignalRService {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentSessionId = undefined
|
this.currentSessionId = undefined
|
||||||
window.location.href = ROUTES_ENUM.protected.admin.classroom.classes
|
window.location.href = ROUTES_ENUM.protected.coordinator.classroom.classes
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
48
ui/src/services/question.service.ts
Normal file
48
ui/src/services/question.service.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { PagedResultDto } from '@/proxy'
|
||||||
|
import apiService from './api.service'
|
||||||
|
import { QuestionDto } from '@/types/coordinator'
|
||||||
|
|
||||||
|
class QuestionService {
|
||||||
|
async getQuestions(): Promise<PagedResultDto<QuestionDto>> {
|
||||||
|
const response = await apiService.fetchData<PagedResultDto<QuestionDto>>({
|
||||||
|
url: '/api/app/question',
|
||||||
|
method: 'GET',
|
||||||
|
})
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async getQuestion(id: string): Promise<QuestionDto> {
|
||||||
|
const response = await apiService.fetchData<QuestionDto>({
|
||||||
|
url: `/api/app/question/${id}`,
|
||||||
|
method: 'GET',
|
||||||
|
})
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateQuestion(id: string, input: QuestionDto) {
|
||||||
|
const response = await apiService.fetchData<QuestionDto>({
|
||||||
|
url: `/api/app/question/${id}`,
|
||||||
|
method: 'PUT',
|
||||||
|
data: input as any,
|
||||||
|
})
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async createQuestion(input: QuestionDto) {
|
||||||
|
const response = await apiService.fetchData<QuestionDto>({
|
||||||
|
method: 'POST',
|
||||||
|
url: '/api/app/question',
|
||||||
|
data: input as any,
|
||||||
|
})
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteQuestion(id: string) {
|
||||||
|
await apiService.fetchData<void>({
|
||||||
|
method: 'DELETE',
|
||||||
|
url: `/api/app/question/${id}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const questionService = new QuestionService()
|
||||||
|
|
@ -14,24 +14,24 @@ export type MediaType = 'image' | 'video';
|
||||||
export type QuestionDifficulty = 'easy' | 'medium' | 'hard';
|
export type QuestionDifficulty = 'easy' | 'medium' | 'hard';
|
||||||
export type ExamSessionStatus = 'in-progress' | 'completed' | 'submitted';
|
export type ExamSessionStatus = 'in-progress' | 'completed' | 'submitted';
|
||||||
|
|
||||||
export interface QuestionPool {
|
export interface QuestionPoolDto {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
questions: Question[];
|
questions: QuestionDto[];
|
||||||
tags: string[];
|
tags: string[];
|
||||||
createdBy: string;
|
createdBy: string;
|
||||||
creationTime: Date;
|
creationTime: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Question {
|
export interface QuestionDto {
|
||||||
id: string;
|
id: string;
|
||||||
type: QuestionType;
|
type: QuestionType;
|
||||||
title: string;
|
title: string;
|
||||||
content: string;
|
content: string;
|
||||||
mediaUrl?: string;
|
mediaUrl?: string;
|
||||||
mediaType?: MediaType;
|
mediaType?: MediaType;
|
||||||
options?: QuestionOption[];
|
options?: QuestionOptionDto[];
|
||||||
correctAnswer?: string | string[];
|
correctAnswer?: string | string[];
|
||||||
points: number;
|
points: number;
|
||||||
timeLimit?: number;
|
timeLimit?: number;
|
||||||
|
|
@ -42,7 +42,7 @@ export interface Question {
|
||||||
lastModificationTime: Date;
|
lastModificationTime: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QuestionOption {
|
export interface QuestionOptionDto {
|
||||||
id: string;
|
id: string;
|
||||||
text: string;
|
text: string;
|
||||||
isCorrect: boolean;
|
isCorrect: boolean;
|
||||||
|
|
@ -60,7 +60,7 @@ export interface Exam {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
answerKeyTemplate?: AnswerKeyItem[];
|
answerKeyTemplate?: AnswerKeyItem[];
|
||||||
questions: Question[];
|
questions: QuestionDto[];
|
||||||
timeLimit: number;
|
timeLimit: number;
|
||||||
totalPoints: number;
|
totalPoints: number;
|
||||||
passingScore: number;
|
passingScore: number;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { QuestionPool, Exam, TagItem, ExamSession } from "@/types/coordinator";
|
import { QuestionPoolDto, Exam, TagItem, ExamSession } from "@/types/coordinator";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
export function useCoordinator() {
|
export function useCoordinator() {
|
||||||
const [currentPath, setCurrentPath] = useState("/admin/dashboard");
|
const [currentPath, setCurrentPath] = useState("/admin/dashboard");
|
||||||
const [pools, setPools] = useState<QuestionPool[]>([]);
|
const [pools, setPools] = useState<QuestionPoolDto[]>([]);
|
||||||
const [exams, setExams] = useState<Exam[]>([]);
|
const [exams, setExams] = useState<Exam[]>([]);
|
||||||
const [tags, setTags] = useState<TagItem[]>([]);
|
const [tags, setTags] = useState<TagItem[]>([]);
|
||||||
const [currentExam, setCurrentExam] = useState<Exam | null>(null);
|
const [currentExam, setCurrentExam] = useState<Exam | null>(null);
|
||||||
|
|
@ -19,9 +19,9 @@ export function useCoordinator() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCreatePool = (
|
const handleCreatePool = (
|
||||||
poolData: Omit<QuestionPool, "id" | "creationTime">
|
poolData: Omit<QuestionPoolDto, "id" | "creationTime">
|
||||||
) => {
|
) => {
|
||||||
const newPool: QuestionPool = {
|
const newPool: QuestionPoolDto = {
|
||||||
...poolData,
|
...poolData,
|
||||||
id: `pool-${Date.now()}`,
|
id: `pool-${Date.now()}`,
|
||||||
creationTime: new Date(),
|
creationTime: new Date(),
|
||||||
|
|
@ -29,7 +29,7 @@ export function useCoordinator() {
|
||||||
setPools((prev) => [...prev, newPool]);
|
setPools((prev) => [...prev, newPool]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdatePool = (updatedPool: QuestionPool) => {
|
const handleUpdatePool = (updatedPool: QuestionPoolDto) => {
|
||||||
setPools((prev) =>
|
setPools((prev) =>
|
||||||
prev.map((pool) => (pool.id === updatedPool.id ? updatedPool : pool))
|
prev.map((pool) => (pool.id === updatedPool.id ? updatedPool : pool))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { QuestionPool, Exam, Question } from "@/types/coordinator";
|
import { QuestionPoolDto, Exam, QuestionDto } from "@/types/coordinator";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { FaPlus, FaClock, FaUsers, FaCog, FaSave } from "react-icons/fa";
|
import { FaPlus, FaClock, FaUsers, FaCog, FaSave } from "react-icons/fa";
|
||||||
|
|
||||||
interface ExamCreatorProps {
|
interface ExamCreatorProps {
|
||||||
pools: QuestionPool[];
|
pools: QuestionPoolDto[];
|
||||||
onCreateExam: (exam: Omit<Exam, "id" | "creationTime" | "lastModificationTime">) => void;
|
onCreateExam: (exam: Omit<Exam, "id" | "creationTime" | "lastModificationTime">) => void;
|
||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
editingExam?: Exam;
|
editingExam?: Exam;
|
||||||
|
|
@ -30,7 +30,7 @@ export const ExamCreator: React.FC<ExamCreatorProps> = ({
|
||||||
isActive: editingExam?.isActive ?? true,
|
isActive: editingExam?.isActive ?? true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [selectedQuestions, setSelectedQuestions] = useState<Question[]>(
|
const [selectedQuestions, setSelectedQuestions] = useState<QuestionDto[]>(
|
||||||
editingExam?.questions || []
|
editingExam?.questions || []
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ import {
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { generateMockExam } from '@/mocks/mockExams'
|
import { generateMockExam } from '@/mocks/mockExams'
|
||||||
import { generateMockPools } from '@/mocks/mockPools'
|
import { generateMockPools } from '@/mocks/mockPools'
|
||||||
import { Exam, QuestionPool } from '@/types/coordinator'
|
import { Exam, QuestionPoolDto } from '@/types/coordinator'
|
||||||
|
|
||||||
const Assignments: React.FC = () => {
|
const Assignments: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [assignments, setAssignments] = useState<Exam[]>(generateMockExam())
|
const [assignments, setAssignments] = useState<Exam[]>(generateMockExam())
|
||||||
const [pools] = useState<QuestionPool[]>(generateMockPools())
|
const [pools] = useState<QuestionPoolDto[]>(generateMockPools())
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [statusFilter, setStatusFilter] = useState('')
|
const [statusFilter, setStatusFilter] = useState('')
|
||||||
const [isCreating, setIsCreating] = useState(false)
|
const [isCreating, setIsCreating] = useState(false)
|
||||||
|
|
|
||||||
|
|
@ -179,13 +179,13 @@ const ClassList: React.FC = () => {
|
||||||
|
|
||||||
const handleJoinClass = (classSession: ClassroomDto) => {
|
const handleJoinClass = (classSession: ClassroomDto) => {
|
||||||
if (classSession.id) {
|
if (classSession.id) {
|
||||||
navigate(ROUTES_ENUM.protected.admin.classroom.roomDetail.replace(':id', classSession.id))
|
navigate(ROUTES_ENUM.protected.coordinator.classroom.roomDetail.replace(':id', classSession.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePlanningClass = (classSession: ClassroomDto) => {
|
const handlePlanningClass = (classSession: ClassroomDto) => {
|
||||||
if (classSession.id) {
|
if (classSession.id) {
|
||||||
navigate(ROUTES_ENUM.protected.admin.classroom.planning.replace(':id', classSession.id))
|
navigate(ROUTES_ENUM.protected.coordinator.classroom.planning.replace(':id', classSession.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +258,7 @@ const ClassList: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<Helmet
|
<Helmet
|
||||||
titleTemplate="%s | Sözsoft Kurs Platform"
|
titleTemplate="%s | Sözsoft Kurs Platform"
|
||||||
title={translate('::' + 'App.Classroom.List')}
|
title={translate('::' + 'App.Coordinator.Classroom.List')}
|
||||||
defaultTitle="Sözsoft Kurs Platform"
|
defaultTitle="Sözsoft Kurs Platform"
|
||||||
></Helmet>
|
></Helmet>
|
||||||
<Container>
|
<Container>
|
||||||
|
|
@ -20,14 +20,14 @@ const Dashboard: React.FC = () => {
|
||||||
role,
|
role,
|
||||||
})
|
})
|
||||||
|
|
||||||
navigate(ROUTES_ENUM.protected.admin.classroom.classes, { replace: true })
|
navigate(ROUTES_ENUM.protected.coordinator.classroom.classes, { replace: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Helmet
|
<Helmet
|
||||||
titleTemplate="%s | Sözsoft Kurs Platform"
|
titleTemplate="%s | Sözsoft Kurs Platform"
|
||||||
title={translate('::' + 'App.Classroom.Dashboard')}
|
title={translate('::' + 'App.Coordinator.Classroom.Dashboard')}
|
||||||
defaultTitle="Sözsoft Kurs Platform"
|
defaultTitle="Sözsoft Kurs Platform"
|
||||||
></Helmet>
|
></Helmet>
|
||||||
<div className="flex items-center justify-center p-4">
|
<div className="flex items-center justify-center p-4">
|
||||||
|
|
@ -164,7 +164,7 @@ const PlanningPage: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<Helmet
|
<Helmet
|
||||||
titleTemplate="%s | Sözsoft Kurs Platform"
|
titleTemplate="%s | Sözsoft Kurs Platform"
|
||||||
title={translate('::' + 'App.Classroom.Planning')}
|
title={translate('::' + 'App.Coordinator.Classroom.Planning')}
|
||||||
defaultTitle="Sözsoft Kurs Platform"
|
defaultTitle="Sözsoft Kurs Platform"
|
||||||
/>
|
/>
|
||||||
<Container>
|
<Container>
|
||||||
|
|
@ -482,12 +482,12 @@ const RoomDetail: React.FC = () => {
|
||||||
await cleanup()
|
await cleanup()
|
||||||
|
|
||||||
// Başka sayfaya yönlendir
|
// Başka sayfaya yönlendir
|
||||||
navigate(ROUTES_ENUM.protected.admin.classroom.classes)
|
navigate(ROUTES_ENUM.protected.coordinator.classroom.classes)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.push(<Notification title="⚠️ Çıkış sırasında hata oluştu" type="warning" />, {
|
toast.push(<Notification title="⚠️ Çıkış sırasında hata oluştu" type="warning" />, {
|
||||||
placement: 'top-end',
|
placement: 'top-end',
|
||||||
})
|
})
|
||||||
navigate(ROUTES_ENUM.protected.admin.classroom.classes)
|
navigate(ROUTES_ENUM.protected.coordinator.classroom.classes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -855,7 +855,7 @@ const RoomDetail: React.FC = () => {
|
||||||
<>
|
<>
|
||||||
<Helmet
|
<Helmet
|
||||||
titleTemplate="%s | Sözsoft Kurs Platform"
|
titleTemplate="%s | Sözsoft Kurs Platform"
|
||||||
title={translate('::' + 'App.Classroom.RoomDetail')}
|
title={translate('::' + 'App.Coordinator.Classroom.RoomDetail')}
|
||||||
defaultTitle="Sözsoft Kurs Platform"
|
defaultTitle="Sözsoft Kurs Platform"
|
||||||
></Helmet>
|
></Helmet>
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
interface ExamNavigationProps {
|
interface ExamNavigationProps {
|
||||||
questions: Question[];
|
questions: QuestionDto[];
|
||||||
answers: StudentAnswer[];
|
answers: StudentAnswer[];
|
||||||
currentQuestionIndex: number;
|
currentQuestionIndex: number;
|
||||||
onQuestionSelect: (index: number) => void;
|
onQuestionSelect: (index: number) => void;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@ import { MultipleChoiceQuestion } from '../QuestionTypes/MultipleChoiceQuestion'
|
||||||
import { OpenEndedQuestion } from '../QuestionTypes/OpenEndedQuestion';
|
import { OpenEndedQuestion } from '../QuestionTypes/OpenEndedQuestion';
|
||||||
import { OrderingQuestion } from '../QuestionTypes/OrderingQuestion';
|
import { OrderingQuestion } from '../QuestionTypes/OrderingQuestion';
|
||||||
import { TrueFalseQuestion } from '../QuestionTypes/TrueFalseQuestion';
|
import { TrueFalseQuestion } from '../QuestionTypes/TrueFalseQuestion';
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
|
|
||||||
interface QuestionRendererProps {
|
interface QuestionRendererProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string | string[]) => void;
|
onAnswerChange: (questionId: string, answer: string | string[]) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ import {
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { generateMockExam } from '@/mocks/mockExams'
|
import { generateMockExam } from '@/mocks/mockExams'
|
||||||
import { generateMockPools } from '@/mocks/mockPools'
|
import { generateMockPools } from '@/mocks/mockPools'
|
||||||
import { Exam, QuestionPool } from '@/types/coordinator'
|
import { Exam, QuestionPoolDto } from '@/types/coordinator'
|
||||||
|
|
||||||
const Exams: React.FC = () => {
|
const Exams: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [exams, setExams] = useState<Exam[]>(generateMockExam())
|
const [exams, setExams] = useState<Exam[]>(generateMockExam())
|
||||||
const [pools] = useState<QuestionPool[]>(generateMockPools())
|
const [pools] = useState<QuestionPoolDto[]>(generateMockPools())
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [statusFilter, setStatusFilter] = useState('')
|
const [statusFilter, setStatusFilter] = useState('')
|
||||||
const [isCreating, setIsCreating] = useState(false)
|
const [isCreating, setIsCreating] = useState(false)
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,49 @@
|
||||||
import { Question, QuestionType, QuestionDifficulty, QuestionOption } from "@/types/coordinator";
|
import { questionService } from '@/services/question.service'
|
||||||
import React, { useState, useEffect } from "react";
|
import {
|
||||||
import { FaSave, FaPlus, FaTrash, FaTimes } from "react-icons/fa";
|
QuestionDto,
|
||||||
|
QuestionType,
|
||||||
|
QuestionDifficulty,
|
||||||
|
QuestionOptionDto,
|
||||||
|
} from '@/types/coordinator'
|
||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import { FaSave, FaPlus, FaTrash, FaTimes } from 'react-icons/fa'
|
||||||
|
|
||||||
interface QuestionEditorProps {
|
function QuestionDialog({
|
||||||
question?: Question;
|
open,
|
||||||
onSave: (question: Omit<Question, "id" | "creationTime" | "lastModificationTime">) => void;
|
onDialogClose,
|
||||||
onCancel: () => void;
|
id,
|
||||||
}
|
}: {
|
||||||
|
open: boolean
|
||||||
export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
onDialogClose: () => void
|
||||||
question,
|
id: string
|
||||||
onSave,
|
}) {
|
||||||
onCancel,
|
const [question, setQuestion] = useState<QuestionDto>()
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
type: "multiple-choice" as QuestionType,
|
type: 'multiple-choice' as QuestionType,
|
||||||
title: "",
|
title: '',
|
||||||
content: "",
|
content: '',
|
||||||
mediaUrl: "",
|
mediaUrl: '',
|
||||||
mediaType: "image" as "image" | "video",
|
mediaType: 'image' as 'image' | 'video',
|
||||||
points: 10,
|
points: 10,
|
||||||
timeLimit: 0,
|
timeLimit: 0,
|
||||||
explanation: "",
|
explanation: '',
|
||||||
tags: [] as string[],
|
difficulty: 'medium' as QuestionDifficulty,
|
||||||
difficulty: "medium" as QuestionDifficulty,
|
})
|
||||||
});
|
|
||||||
|
|
||||||
const [options, setOptions] = useState<QuestionOption[]>([]);
|
const [options, setOptions] = useState<QuestionOptionDto[]>([])
|
||||||
const [correctAnswer, setCorrectAnswer] = useState<string | string[]>("");
|
const [correctAnswer, setCorrectAnswer] = useState<string | string[]>('')
|
||||||
const [tagInput, setTagInput] = useState("");
|
const [tagInput, setTagInput] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchQuestion = async () => {
|
||||||
|
if (open) {
|
||||||
|
const entity = await questionService.getQuestion(id)
|
||||||
|
setQuestion(entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchQuestion()
|
||||||
|
}, [open])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (question) {
|
if (question) {
|
||||||
|
|
@ -36,136 +51,103 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
type: question.type,
|
type: question.type,
|
||||||
title: question.title,
|
title: question.title,
|
||||||
content: question.content,
|
content: question.content,
|
||||||
mediaUrl: question.mediaUrl || "",
|
mediaUrl: question.mediaUrl || '',
|
||||||
mediaType: question.mediaType || "image",
|
mediaType: question.mediaType || 'image',
|
||||||
points: question.points,
|
points: question.points,
|
||||||
timeLimit: question.timeLimit || 0,
|
timeLimit: question.timeLimit || 0,
|
||||||
explanation: question.explanation || "",
|
explanation: question.explanation || '',
|
||||||
tags: question.tags,
|
|
||||||
difficulty: question.difficulty,
|
difficulty: question.difficulty,
|
||||||
});
|
})
|
||||||
setOptions(question.options || []);
|
setOptions(question.options || [])
|
||||||
setCorrectAnswer(question.correctAnswer || "");
|
setCorrectAnswer(question.correctAnswer || '')
|
||||||
}
|
}
|
||||||
}, [question]);
|
}, [question])
|
||||||
|
|
||||||
const handleInputChange = (field: string, value: any) => {
|
const handleInputChange = (field: string, value: any) => {
|
||||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
setFormData((prev) => ({ ...prev, [field]: value }))
|
||||||
};
|
}
|
||||||
|
|
||||||
const addOption = () => {
|
const addOption = () => {
|
||||||
const newOption: QuestionOption = {
|
const newOption: QuestionOptionDto = {
|
||||||
id: `opt-${Date.now()}`,
|
id: `opt-${Date.now()}`,
|
||||||
text: "",
|
text: '',
|
||||||
isCorrect: false,
|
isCorrect: false,
|
||||||
order: options.length,
|
order: options.length,
|
||||||
};
|
}
|
||||||
setOptions((prev) => [...prev, newOption]);
|
setOptions((prev) => [...prev, newOption])
|
||||||
};
|
}
|
||||||
|
|
||||||
const updateOption = (index: number, field: string, value: any) => {
|
const updateOption = (index: number, field: string, value: any) => {
|
||||||
setOptions((prev) =>
|
setOptions((prev) => prev.map((opt, i) => (i === index ? { ...opt, [field]: value } : opt)))
|
||||||
prev.map((opt, i) => (i === index ? { ...opt, [field]: value } : opt))
|
}
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeOption = (index: number) => {
|
const removeOption = (index: number) => {
|
||||||
setOptions((prev) => prev.filter((_, i) => i !== index));
|
setOptions((prev) => prev.filter((_, i) => i !== index))
|
||||||
};
|
}
|
||||||
|
|
||||||
const addTag = () => {
|
|
||||||
if (tagInput.trim() && !formData.tags.includes(tagInput.trim())) {
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
tags: [...prev.tags, tagInput.trim()],
|
|
||||||
}));
|
|
||||||
setTagInput("");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeTag = (tag: string) => {
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
tags: prev.tags.filter((t) => t !== tag),
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
if (!formData.title.trim() || !formData.content.trim()) {
|
if (!formData.title.trim() || !formData.content.trim()) {
|
||||||
alert("Please fill in the title and content fields.");
|
alert('Please fill in the title and content fields.')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.points <= 0) {
|
if (formData.points <= 0) {
|
||||||
alert("Points must be greater than 0.");
|
alert('Points must be greater than 0.')
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate based on question type
|
// Validate based on question type
|
||||||
if (
|
if (['multiple-choice', 'multiple-answer'].includes(formData.type) && options.length < 2) {
|
||||||
["multiple-choice", "multiple-answer"].includes(formData.type) &&
|
alert('Please add at least 2 options.')
|
||||||
options.length < 2
|
return
|
||||||
) {
|
|
||||||
alert("Please add at least 2 options.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (formData.type === 'multiple-choice' && !options.some((opt) => opt.isCorrect)) {
|
||||||
formData.type === "multiple-choice" &&
|
alert('Please mark the correct answer.')
|
||||||
!options.some((opt) => opt.isCorrect)
|
return
|
||||||
) {
|
|
||||||
alert("Please mark the correct answer.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const questionData = {
|
const questionData = {
|
||||||
...formData,
|
...formData,
|
||||||
options: [
|
options: ['multiple-choice', 'multiple-answer', 'matching', 'ordering'].includes(
|
||||||
"multiple-choice",
|
formData.type,
|
||||||
"multiple-answer",
|
)
|
||||||
"matching",
|
|
||||||
"ordering",
|
|
||||||
].includes(formData.type)
|
|
||||||
? options
|
? options
|
||||||
: undefined,
|
: undefined,
|
||||||
correctAnswer: getCorrectAnswer(),
|
correctAnswer: getCorrectAnswer(),
|
||||||
};
|
}
|
||||||
|
|
||||||
onSave(questionData);
|
// onSave(questionData)
|
||||||
};
|
}
|
||||||
|
|
||||||
const getCorrectAnswer = (): string | string[] => {
|
const getCorrectAnswer = (): string | string[] => {
|
||||||
switch (formData.type) {
|
switch (formData.type) {
|
||||||
case "multiple-choice":
|
case 'multiple-choice':
|
||||||
return options.find((opt) => opt.isCorrect)?.id || "";
|
return options.find((opt) => opt.isCorrect)?.id || ''
|
||||||
case "multiple-answer":
|
case 'multiple-answer':
|
||||||
return options.filter((opt) => opt.isCorrect).map((opt) => opt.id);
|
return options.filter((opt) => opt.isCorrect).map((opt) => opt.id)
|
||||||
case "true-false":
|
case 'true-false':
|
||||||
return correctAnswer as string;
|
return correctAnswer as string
|
||||||
case "fill-blank":
|
case 'fill-blank':
|
||||||
case "open-ended":
|
case 'open-ended':
|
||||||
case "calculation":
|
case 'calculation':
|
||||||
return correctAnswer as string;
|
return correctAnswer as string
|
||||||
case "matching":
|
case 'matching':
|
||||||
return options.map((opt) => opt.id);
|
return options.map((opt) => opt.id)
|
||||||
case "ordering":
|
case 'ordering':
|
||||||
return options
|
return options.sort((a, b) => (a.order || 0) - (b.order || 0)).map((opt) => opt.id)
|
||||||
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
||||||
.map((opt) => opt.id);
|
|
||||||
default:
|
default:
|
||||||
return correctAnswer as string;
|
return correctAnswer as string
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const renderQuestionTypeSpecificFields = () => {
|
const renderQuestionTypeSpecificFields = () => {
|
||||||
switch (formData.type) {
|
switch (formData.type) {
|
||||||
case "multiple-choice":
|
case 'multiple-choice':
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h4 className="text-sm font-medium text-gray-900">
|
<h4 className="text-sm font-medium text-gray-900">Yanıtlar (A, B, C, D, E)</h4>
|
||||||
Yanıtlar (A, B, C, D, E)
|
|
||||||
</h4>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={addOption}
|
onClick={addOption}
|
||||||
|
|
@ -194,15 +176,15 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
prev.map((opt, i) => ({
|
prev.map((opt, i) => ({
|
||||||
...opt,
|
...opt,
|
||||||
isCorrect: i === index ? e.target.checked : false,
|
isCorrect: i === index ? e.target.checked : false,
|
||||||
}))
|
})),
|
||||||
);
|
)
|
||||||
}}
|
}}
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={option.text}
|
value={option.text}
|
||||||
onChange={(e) => updateOption(index, "text", e.target.value)}
|
onChange={(e) => updateOption(index, 'text', e.target.value)}
|
||||||
placeholder={`${String.fromCharCode(65 + index)} şıkkı`}
|
placeholder={`${String.fromCharCode(65 + index)} şıkkı`}
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
|
|
@ -216,9 +198,9 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "multiple-answer":
|
case 'multiple-answer':
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -243,21 +225,17 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={option.isCorrect}
|
checked={option.isCorrect}
|
||||||
onChange={(e) =>
|
onChange={(e) => updateOption(index, 'isCorrect', e.target.checked)}
|
||||||
updateOption(index, "isCorrect", e.target.checked)
|
|
||||||
}
|
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={option.text}
|
value={option.text}
|
||||||
onChange={(e) => updateOption(index, "text", e.target.value)}
|
onChange={(e) => updateOption(index, 'text', e.target.value)}
|
||||||
placeholder={`Yanıt ${index + 1}`}
|
placeholder={`Yanıt ${index + 1}`}
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
<div className="text-sm text-gray-600">
|
<div className="text-sm text-gray-600">{option.isCorrect ? 'Doğru' : 'Yanlış'}</div>
|
||||||
{option.isCorrect ? "Doğru" : "Yanlış"}
|
|
||||||
</div>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => removeOption(index)}
|
onClick={() => removeOption(index)}
|
||||||
|
|
@ -268,21 +246,19 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "true-false":
|
case 'true-false':
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Doğru Cevap</label>
|
||||||
Doğru Cevap
|
|
||||||
</label>
|
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
<label className="flex items-center">
|
<label className="flex items-center">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="true-false"
|
name="true-false"
|
||||||
value="true"
|
value="true"
|
||||||
checked={correctAnswer === "true"}
|
checked={correctAnswer === 'true'}
|
||||||
onChange={(e) => setCorrectAnswer(e.target.value)}
|
onChange={(e) => setCorrectAnswer(e.target.value)}
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
|
||||||
/>
|
/>
|
||||||
|
|
@ -293,7 +269,7 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
type="radio"
|
type="radio"
|
||||||
name="true-false"
|
name="true-false"
|
||||||
value="false"
|
value="false"
|
||||||
checked={correctAnswer === "false"}
|
checked={correctAnswer === 'false'}
|
||||||
onChange={(e) => setCorrectAnswer(e.target.value)}
|
onChange={(e) => setCorrectAnswer(e.target.value)}
|
||||||
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
|
className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300"
|
||||||
/>
|
/>
|
||||||
|
|
@ -301,9 +277,9 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "fill-blank":
|
case 'fill-blank':
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
|
|
@ -314,9 +290,7 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{Array.from({ length: 10 }, (_, index) => {
|
{Array.from({ length: 10 }, (_, index) => {
|
||||||
const blankAnswers = ((correctAnswer as string) || "").split(
|
const blankAnswers = ((correctAnswer as string) || '').split('|')
|
||||||
"|"
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<div key={index} className="flex items-center space-x-3">
|
<div key={index} className="flex items-center space-x-3">
|
||||||
<div className="bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1 rounded min-w-16 text-center">
|
<div className="bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1 rounded min-w-16 text-center">
|
||||||
|
|
@ -324,41 +298,35 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={blankAnswers[index] || ""}
|
value={blankAnswers[index] || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const newAnswers = [...blankAnswers];
|
const newAnswers = [...blankAnswers]
|
||||||
newAnswers[index] = e.target.value;
|
newAnswers[index] = e.target.value
|
||||||
// Remove empty answers from the end
|
// Remove empty answers from the end
|
||||||
while (
|
while (newAnswers.length > 0 && !newAnswers[newAnswers.length - 1]) {
|
||||||
newAnswers.length > 0 &&
|
newAnswers.pop()
|
||||||
!newAnswers[newAnswers.length - 1]
|
|
||||||
) {
|
|
||||||
newAnswers.pop();
|
|
||||||
}
|
}
|
||||||
setCorrectAnswer(newAnswers.join("|"));
|
setCorrectAnswer(newAnswers.join('|'))
|
||||||
}}
|
}}
|
||||||
placeholder={`${index + 1}. boşluk için kelime/cümle`}
|
placeholder={`${index + 1}. boşluk için kelime/cümle`}
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-xs text-gray-500 mt-2">
|
<p className="text-xs text-gray-500 mt-2">
|
||||||
Soru içeriğinde _____ veya [blank] kullanarak boşlukları
|
Soru içeriğinde _____ veya [blank] kullanarak boşlukları işaretleyin
|
||||||
işaretleyin
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "matching":
|
case 'matching':
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h4 className="text-md font-medium text-gray-900">
|
<h4 className="text-md font-medium text-gray-900">Eşleştirme Çiftleri</h4>
|
||||||
Eşleştirme Çiftleri
|
|
||||||
</h4>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={addOption}
|
onClick={addOption}
|
||||||
|
|
@ -376,14 +344,10 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={option.text.split("|")[0] || ""}
|
value={option.text.split('|')[0] || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const rightSide = option.text.split("|")[1] || "";
|
const rightSide = option.text.split('|')[1] || ''
|
||||||
updateOption(
|
updateOption(index, 'text', `${e.target.value}|${rightSide}`)
|
||||||
index,
|
|
||||||
"text",
|
|
||||||
`${e.target.value}|${rightSide}`
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
placeholder="Sol taraf (örn: PLUS)"
|
placeholder="Sol taraf (örn: PLUS)"
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
|
|
@ -391,14 +355,10 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
<span className="text-gray-400">↔</span>
|
<span className="text-gray-400">↔</span>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={option.text.split("|")[1] || ""}
|
value={option.text.split('|')[1] || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const leftSide = option.text.split("|")[0] || "";
|
const leftSide = option.text.split('|')[0] || ''
|
||||||
updateOption(
|
updateOption(index, 'text', `${leftSide}|${e.target.value}`)
|
||||||
index,
|
|
||||||
"text",
|
|
||||||
`${leftSide}|${e.target.value}`
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
placeholder="Sağ taraf (örn: ARTI)"
|
placeholder="Sağ taraf (örn: ARTI)"
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
|
|
@ -413,15 +373,13 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "ordering":
|
case 'ordering':
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h4 className="text-md font-medium text-gray-900">
|
<h4 className="text-md font-medium text-gray-900">Sıralanacak Öğeler</h4>
|
||||||
Sıralanacak Öğeler
|
|
||||||
</h4>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={addOption}
|
onClick={addOption}
|
||||||
|
|
@ -443,16 +401,14 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={option.order || index + 1}
|
value={option.order || index + 1}
|
||||||
onChange={(e) =>
|
onChange={(e) => updateOption(index, 'order', parseInt(e.target.value))}
|
||||||
updateOption(index, "order", parseInt(e.target.value))
|
|
||||||
}
|
|
||||||
min="1"
|
min="1"
|
||||||
className="w-20 text-sm border border-gray-300 rounded-lg px-2 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-20 text-sm border border-gray-300 rounded-lg px-2 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={option.text}
|
value={option.text}
|
||||||
onChange={(e) => updateOption(index, "text", e.target.value)}
|
onChange={(e) => updateOption(index, 'text', e.target.value)}
|
||||||
placeholder={`Öğe ${index + 1} (örn: I, TAKE, A SHOWER)`}
|
placeholder={`Öğe ${index + 1} (örn: I, TAKE, A SHOWER)`}
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
|
|
@ -467,13 +423,12 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<p className="text-xs text-gray-500 mt-2">
|
<p className="text-xs text-gray-500 mt-2">
|
||||||
Öğrenciler bu öğeleri doğru sıraya göre düzenleyecek (drag & drop
|
Öğrenciler bu öğeleri doğru sıraya göre düzenleyecek (drag & drop veya butonlarla)
|
||||||
veya butonlarla)
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "open-ended":
|
case 'open-ended':
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
|
|
@ -486,13 +441,11 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
rows={4}
|
rows={4}
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 mt-1">
|
<p className="text-xs text-gray-500 mt-1">Öğrenci bu soruya açıklama yazabilecek</p>
|
||||||
Öğrenci bu soruya açıklama yazabilecek
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
case "calculation":
|
case 'calculation':
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
|
|
@ -509,24 +462,21 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
Öğrenci matematiksel hesaplama yapıp sayısal sonuç yazacak
|
Öğrenci matematiksel hesaplama yapıp sayısal sonuç yazacak
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
|
||||||
<div className="bg-white rounded-lg max-w-4xl w-full max-h-[90vh] overflow-y-auto">
|
<div className="bg-white rounded-lg max-w-4xl w-full max-h-[90vh] overflow-y-auto">
|
||||||
<div className="sticky top-0 bg-white border-b border-gray-200 px-5 py-3 flex items-center justify-between">
|
<div className="sticky top-0 bg-white border-b border-gray-200 px-5 py-3 flex items-center justify-between">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">
|
<h2 className="text-lg font-semibold text-gray-900">
|
||||||
{question ? "Edit Question" : "Create New Question"}
|
{question ? 'Edit Question' : 'Create New Question'}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button onClick={onDialogClose} className="text-gray-400 hover:text-gray-600">
|
||||||
onClick={onCancel}
|
|
||||||
className="text-gray-400 hover:text-gray-600"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-5 h-5" />
|
<FaTimes className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -540,7 +490,7 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
value={formData.type}
|
value={formData.type}
|
||||||
onChange={(e) => handleInputChange("type", e.target.value)}
|
onChange={(e) => handleInputChange('type', e.target.value)}
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="multiple-choice">Multiple Choice</option>
|
<option value="multiple-choice">Multiple Choice</option>
|
||||||
|
|
@ -555,15 +505,11 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Points</label>
|
||||||
Points
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={formData.points}
|
value={formData.points}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('points', parseInt(e.target.value))}
|
||||||
handleInputChange("points", parseInt(e.target.value))
|
|
||||||
}
|
|
||||||
min="1"
|
min="1"
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
|
|
@ -571,25 +517,21 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Question Title</label>
|
||||||
Question Title
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={formData.title}
|
value={formData.title}
|
||||||
onChange={(e) => handleInputChange("title", e.target.value)}
|
onChange={(e) => handleInputChange('title', e.target.value)}
|
||||||
placeholder="Enter question title..."
|
placeholder="Enter question title..."
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Question Content</label>
|
||||||
Question Content
|
|
||||||
</label>
|
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.content}
|
value={formData.content}
|
||||||
onChange={(e) => handleInputChange("content", e.target.value)}
|
onChange={(e) => handleInputChange('content', e.target.value)}
|
||||||
placeholder="Enter the question content..."
|
placeholder="Enter the question content..."
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
rows={4}
|
rows={4}
|
||||||
|
|
@ -605,19 +547,17 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
<input
|
<input
|
||||||
type="url"
|
type="url"
|
||||||
value={formData.mediaUrl}
|
value={formData.mediaUrl}
|
||||||
onChange={(e) => handleInputChange("mediaUrl", e.target.value)}
|
onChange={(e) => handleInputChange('mediaUrl', e.target.value)}
|
||||||
placeholder="https://example.com/image.jpg"
|
placeholder="https://example.com/image.jpg"
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">
|
<label className="block text-sm font-medium text-gray-700 mb-1.5">Media Type</label>
|
||||||
Media Type
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.mediaType}
|
value={formData.mediaType}
|
||||||
onChange={(e) => handleInputChange("mediaType", e.target.value)}
|
onChange={(e) => handleInputChange('mediaType', e.target.value)}
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="image">Image</option>
|
<option value="image">Image</option>
|
||||||
|
|
@ -632,14 +572,10 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
{/* Additional Settings */}
|
{/* Additional Settings */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">Difficulty</label>
|
||||||
Difficulty
|
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
value={formData.difficulty}
|
value={formData.difficulty}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('difficulty', e.target.value)}
|
||||||
handleInputChange("difficulty", e.target.value)
|
|
||||||
}
|
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
>
|
>
|
||||||
<option value="easy">Easy</option>
|
<option value="easy">Easy</option>
|
||||||
|
|
@ -655,71 +591,20 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={formData.timeLimit}
|
value={formData.timeLimit}
|
||||||
onChange={(e) =>
|
onChange={(e) => handleInputChange('timeLimit', parseInt(e.target.value))}
|
||||||
handleInputChange("timeLimit", parseInt(e.target.value))
|
|
||||||
}
|
|
||||||
min="0"
|
min="0"
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
||||||
Add Tag
|
|
||||||
</label>
|
|
||||||
<div className="flex space-x-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={tagInput}
|
|
||||||
onChange={(e) => setTagInput(e.target.value)}
|
|
||||||
onKeyPress={(e) => e.key === "Enter" && addTag()}
|
|
||||||
placeholder="grammar, vocabulary..."
|
|
||||||
className="flex-1 text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={addTag}
|
|
||||||
className="px-3 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
|
||||||
>
|
|
||||||
<FaPlus className="w-4 h-4" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Tags Display */}
|
|
||||||
{formData.tags.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">
|
|
||||||
Tags
|
|
||||||
</label>
|
|
||||||
<div className="flex flex-wrap gap-1.5">
|
|
||||||
{formData.tags.map((tag) => (
|
|
||||||
<span
|
|
||||||
key={tag}
|
|
||||||
className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => removeTag(tag)}
|
|
||||||
className="ml-1.5 text-blue-600 hover:text-blue-800"
|
|
||||||
>
|
|
||||||
<FaTimes className="w-2.5 h-2.5" />
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1.5">
|
<label className="block text-sm font-medium text-gray-700 mb-1.5">
|
||||||
Explanation (Optional)
|
Explanation (Optional)
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
value={formData.explanation}
|
value={formData.explanation}
|
||||||
onChange={(e) => handleInputChange("explanation", e.target.value)}
|
onChange={(e) => handleInputChange('explanation', e.target.value)}
|
||||||
placeholder="Provide an explanation for the correct answer..."
|
placeholder="Provide an explanation for the correct answer..."
|
||||||
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
className="w-full text-sm border border-gray-300 rounded-lg px-2 py-1 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||||
rows={3}
|
rows={3}
|
||||||
|
|
@ -730,7 +615,7 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="sticky bottom-0 bg-gray-50 border-t border-gray-200 px-5 py-3 flex justify-end space-x-2">
|
<div className="sticky bottom-0 bg-gray-50 border-t border-gray-200 px-5 py-3 flex justify-end space-x-2">
|
||||||
<button
|
<button
|
||||||
onClick={onCancel}
|
onClick={onDialogClose}
|
||||||
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 font-medium transition-colors"
|
className="px-3 py-1.5 text-sm border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 font-medium transition-colors"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|
@ -745,5 +630,7 @@ export const QuestionEditor: React.FC<QuestionEditorProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
|
export default QuestionDialog
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { QuestionEditor } from "./QuestionEditor";
|
|
||||||
import { FaPlus, FaSearch, FaFilter, FaEdit, FaTrash } from "react-icons/fa";
|
import { FaPlus, FaSearch, FaFilter, FaEdit, FaTrash } from "react-icons/fa";
|
||||||
import { generateMockPools } from "@/mocks/mockPools";
|
import { generateMockPools } from "@/mocks/mockPools";
|
||||||
import { QuestionPool, Question } from "@/types/coordinator";
|
import { QuestionPoolDto, QuestionDto } from "@/types/coordinator";
|
||||||
|
import QuestionDialog from "./QuestionDialog";
|
||||||
|
|
||||||
export const QuestionPoolManager: React.FC = () => {
|
export const QuestionPoolManager: React.FC = () => {
|
||||||
const [pools, setPools] = useState<QuestionPool[]>(generateMockPools());
|
const [pools, setPools] = useState<QuestionPoolDto[]>(generateMockPools());
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [selectedTag, setSelectedTag] = useState("");
|
const [selectedTag, setSelectedTag] = useState("");
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
const [isCreating, setIsCreating] = useState(false);
|
||||||
const [editingPool, setEditingPool] = useState<QuestionPool | null>(null);
|
const [editingPool, setEditingPool] = useState<QuestionPoolDto | null>(null);
|
||||||
const [editingQuestion, setEditingQuestion] = useState<Question | null>(null);
|
const [editingQuestion, setEditingQuestion] = useState<QuestionDto | null>(null);
|
||||||
const [showQuestionEditor, setShowQuestionEditor] = useState(false);
|
const [showQuestionEditor, setShowQuestionEditor] = useState(false);
|
||||||
const [selectedPoolForQuestion, setSelectedPoolForQuestion] =
|
const [selectedPoolForQuestion, setSelectedPoolForQuestion] =
|
||||||
useState<string>("");
|
useState<string>("");
|
||||||
|
|
@ -34,7 +34,7 @@ export const QuestionPoolManager: React.FC = () => {
|
||||||
const handleCreatePool = () => {
|
const handleCreatePool = () => {
|
||||||
if (!newPool.name.trim()) return;
|
if (!newPool.name.trim()) return;
|
||||||
|
|
||||||
const newPoolData: QuestionPool = {
|
const newPoolData: QuestionPoolDto = {
|
||||||
id: `pool-${Date.now()}`,
|
id: `pool-${Date.now()}`,
|
||||||
name: newPool.name,
|
name: newPool.name,
|
||||||
description: newPool.description,
|
description: newPool.description,
|
||||||
|
|
@ -63,19 +63,19 @@ export const QuestionPoolManager: React.FC = () => {
|
||||||
setShowQuestionEditor(true);
|
setShowQuestionEditor(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEditQuestion = (question: Question, poolId: string) => {
|
const handleEditQuestion = (question: QuestionDto, poolId: string) => {
|
||||||
setSelectedPoolForQuestion(poolId);
|
setSelectedPoolForQuestion(poolId);
|
||||||
setEditingQuestion(question);
|
setEditingQuestion(question);
|
||||||
setShowQuestionEditor(true);
|
setShowQuestionEditor(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveQuestion = (
|
const handleSaveQuestion = (
|
||||||
questionData: Omit<Question, "id" | "creationTime" | "lastModificationTime">
|
questionData: Omit<QuestionDto, "id" | "creationTime" | "lastModificationTime">
|
||||||
) => {
|
) => {
|
||||||
const pool = pools.find((p) => p.id === selectedPoolForQuestion);
|
const pool = pools.find((p) => p.id === selectedPoolForQuestion);
|
||||||
if (!pool) return;
|
if (!pool) return;
|
||||||
|
|
||||||
const newQuestion: Question = {
|
const newQuestion: QuestionDto = {
|
||||||
...questionData,
|
...questionData,
|
||||||
id: editingQuestion?.id || `q-${Date.now()}`,
|
id: editingQuestion?.id || `q-${Date.now()}`,
|
||||||
creationTime: editingQuestion?.creationTime || new Date(),
|
creationTime: editingQuestion?.creationTime || new Date(),
|
||||||
|
|
@ -278,7 +278,7 @@ export const QuestionPoolManager: React.FC = () => {
|
||||||
|
|
||||||
{/* Question Editor Modal */}
|
{/* Question Editor Modal */}
|
||||||
{showQuestionEditor && (
|
{showQuestionEditor && (
|
||||||
<QuestionEditor
|
<QuestionDialog
|
||||||
question={editingQuestion || undefined}
|
question={editingQuestion || undefined}
|
||||||
onSave={handleSaveQuestion}
|
onSave={handleSaveQuestion}
|
||||||
onCancel={() => setShowQuestionEditor(false)}
|
onCancel={() => setShowQuestionEditor(false)}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface CalculationQuestionProps {
|
interface CalculationQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string) => void;
|
onAnswerChange: (questionId: string, answer: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface FillBlankQuestionProps {
|
interface FillBlankQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string[]) => void;
|
onAnswerChange: (questionId: string, answer: string[]) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface MatchingQuestionProps {
|
interface MatchingQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string[]) => void;
|
onAnswerChange: (questionId: string, answer: string[]) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface MultipleAnswerQuestionProps {
|
interface MultipleAnswerQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string[]) => void;
|
onAnswerChange: (questionId: string, answer: string[]) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
interface MultipleChoiceQuestionProps {
|
interface MultipleChoiceQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string) => void;
|
onAnswerChange: (questionId: string, answer: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface OpenEndedQuestionProps {
|
interface OpenEndedQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string) => void;
|
onAnswerChange: (questionId: string, answer: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
|
||||||
interface OrderingQuestionProps {
|
interface OrderingQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string[]) => void;
|
onAnswerChange: (questionId: string, answer: string[]) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Question, StudentAnswer } from '@/types/coordinator';
|
import { QuestionDto, StudentAnswer } from '@/types/coordinator';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
interface TrueFalseQuestionProps {
|
interface TrueFalseQuestionProps {
|
||||||
question: Question;
|
question: QuestionDto;
|
||||||
answer?: StudentAnswer;
|
answer?: StudentAnswer;
|
||||||
onAnswerChange: (questionId: string, answer: string) => void;
|
onAnswerChange: (questionId: string, answer: string) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ const TagBoxEditorComponent = ({
|
||||||
{...editorOptions}
|
{...editorOptions}
|
||||||
{...(setDefaultValue ? { defaultValue: val } : { value: val })}
|
{...(setDefaultValue ? { defaultValue: val } : { value: val })}
|
||||||
dataSource={editorOptions?.dataSource}
|
dataSource={editorOptions?.dataSource}
|
||||||
valueExpr={lookupDto?.valueExpr}
|
valueExpr={lookupDto?.valueExpr?.toLocaleLowerCase()}
|
||||||
displayExpr={lookupDto?.displayExpr}
|
displayExpr={lookupDto?.displayExpr?.toLocaleLowerCase()}
|
||||||
showClearButton={options?.showClearButton}
|
showClearButton={options?.showClearButton}
|
||||||
showSelectionControls={options?.showSelectionControls ?? true}
|
showSelectionControls={options?.showSelectionControls ?? true}
|
||||||
maxDisplayedTags={options?.maxDisplayedTags}
|
maxDisplayedTags={options?.maxDisplayedTags}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import AuditLogDetail from '@/views/admin/auditLog/AuditLogDetail'
|
||||||
import RolesPermission from '@/views/admin/role-management/RolesPermission'
|
import RolesPermission from '@/views/admin/role-management/RolesPermission'
|
||||||
import UsersPermission from '@/views/admin/user-management/UsersPermission'
|
import UsersPermission from '@/views/admin/user-management/UsersPermission'
|
||||||
import BranchSeed from '@/views/branch/BranchSeed'
|
import BranchSeed from '@/views/branch/BranchSeed'
|
||||||
|
import QuestionDialog from '@/views/coordinator/QuestionDialog'
|
||||||
|
|
||||||
const DialogShowComponent = (): JSX.Element => {
|
const DialogShowComponent = (): JSX.Element => {
|
||||||
const dialogContext: any = useDialogContext()
|
const dialogContext: any = useDialogContext()
|
||||||
|
|
@ -59,6 +60,14 @@ const DialogShowComponent = (): JSX.Element => {
|
||||||
{...dialogContext.config?.props}
|
{...dialogContext.config?.props}
|
||||||
></BranchSeed>
|
></BranchSeed>
|
||||||
)
|
)
|
||||||
|
case 'QuestionAnswers':
|
||||||
|
return (
|
||||||
|
<QuestionDialog
|
||||||
|
open={true}
|
||||||
|
onDialogClose={() => dialogContext.setConfig({})}
|
||||||
|
{...dialogContext.config?.props}
|
||||||
|
></QuestionDialog>
|
||||||
|
)
|
||||||
default:
|
default:
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue