Developer Kit güncellemeleri

This commit is contained in:
Sedat ÖZTÜRK 2025-11-05 12:02:16 +03:00
parent 5df821f513
commit 7c4bfd4b41
40 changed files with 659 additions and 14439 deletions

View file

@ -3,7 +3,7 @@ using Volo.Abp.Application.Dtos;
namespace Kurs.Platform.DeveloperKit;
public class ApiEndpointDto : FullAuditedEntityDto<Guid>
public class CrudEndpointDto : FullAuditedEntityDto<Guid>
{
public string EntityName { get; set; } = string.Empty;
public string Method { get; set; } = string.Empty;
@ -17,7 +17,7 @@ public class ApiEndpointDto : FullAuditedEntityDto<Guid>
public string? EntityDisplayName { get; set; }
}
public class CreateUpdateApiEndpointDto
public class CreateUpdateCrudEndpointDto
{
public string EntityName { get; set; } = string.Empty;
public string Method { get; set; } = string.Empty;

View file

@ -4,7 +4,7 @@ using Volo.Abp.Application.Dtos;
namespace Kurs.Platform.DeveloperKit;
public class ApiMigrationDto : AuditedEntityDto<Guid>
public class CrudMigrationDto : AuditedEntityDto<Guid>
{
public Guid EntityId { get; set; }
public string EntityName { get; set; } = string.Empty;
@ -15,7 +15,7 @@ public class ApiMigrationDto : AuditedEntityDto<Guid>
public string? ErrorMessage { get; set; }
}
public class CreateUpdateApiMigrationDto
public class CreateUpdateCrudMigrationDto
{
public Guid EntityId { get; set; }
public string EntityName { get; set; } = string.Empty;

View file

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Platform.DeveloperKit;
public interface IApiEndpointAppService : ICrudAppService<
ApiEndpointDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateApiEndpointDto>
{
Task<List<ApiEndpointDto>> GetActiveEndpointsAsync();
Task<List<ApiEndpointDto>> GetEndpointsByEntityAsync(Guid entityId);
Task<PagedResultDto<ApiEndpointDto>> GenerateCrudEndpointsAsync(Guid entityId);
}

View file

@ -1,18 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Platform.DeveloperKit;
public interface IApiMigrationAppService : ICrudAppService<
ApiMigrationDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateApiMigrationDto>
{
Task<ApiMigrationDto> ApplyMigrationAsync(Guid id);
Task<List<ApiMigrationDto>> GetPendingMigrationsAsync();
Task<ApiMigrationDto> GenerateMigrationAsync(Guid entityId);
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Platform.DeveloperKit;
public interface ICrudEndpointAppService : ICrudAppService<
CrudEndpointDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateCrudEndpointDto>
{
Task<List<CrudEndpointDto>> GetActiveEndpointsAsync();
Task<List<CrudEndpointDto>> GetEndpointsByEntityAsync(Guid entityId);
Task<PagedResultDto<CrudEndpointDto>> GenerateCrudEndpointsAsync(Guid entityId);
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace Kurs.Platform.DeveloperKit;
public interface ICrudMigrationAppService : ICrudAppService<
CrudMigrationDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateCrudMigrationDto>
{
Task<CrudMigrationDto> ApplyMigrationAsync(Guid id);
Task<List<CrudMigrationDto>> GetPendingMigrationsAsync();
Task<CrudMigrationDto> GenerateMigrationAsync(Guid entityId);
}

View file

@ -12,14 +12,14 @@ using Volo.Abp.Domain.Repositories;
namespace Kurs.Platform.Application;
[RemoteService]
[Route("api/app/dynamic")]
public class DynamicAppService : ApplicationService
[Route("api/app/crudendpoint")]
public class CrudEndpointAppService : ApplicationService
{
private readonly IRepository<ApiEndpoint, Guid> _endpointRepository;
private readonly IRepository<CrudEndpoint, Guid> _endpointRepository;
private readonly IDynamicEntityManager _dynamicManager;
public DynamicAppService(
IRepository<ApiEndpoint, Guid> endpointRepository,
public CrudEndpointAppService(
IRepository<CrudEndpoint, Guid> endpointRepository,
IDynamicEntityManager dynamicManager)
{
_endpointRepository = endpointRepository;

View file

@ -11,23 +11,22 @@ using Volo.Abp.Domain.Repositories;
namespace Platform.Api.Application;
public class ApiEndpointAppService : CrudAppService<
ApiEndpoint,
ApiEndpointDto,
public class CrudEndpointGenerateAppService : CrudAppService<
CrudEndpoint,
CrudEndpointDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateApiEndpointDto>, IApiEndpointAppService
CreateUpdateCrudEndpointDto>, ICrudEndpointAppService
{
private readonly IRepository<CustomEntity, Guid> _entityRepository;
private readonly IRepository<ApiMigration, Guid> _migrationRepository;
private readonly IRepository<ApiEndpoint, Guid> _endpointRepository;
private readonly IRepository<CrudMigration, Guid> _migrationRepository;
private readonly IRepository<CrudEndpoint, Guid> _endpointRepository;
public ApiEndpointAppService(
IRepository<ApiEndpoint, Guid> repository,
public CrudEndpointGenerateAppService(
IRepository<CrudEndpoint, Guid> repository,
IRepository<CustomEntity, Guid> entityRepository,
IRepository<ApiMigration, Guid> migrationRepository,
IRepository<ApiEndpoint, Guid> endpointRepository)
IRepository<CrudMigration, Guid> migrationRepository,
IRepository<CrudEndpoint, Guid> endpointRepository)
: base(repository)
{
_entityRepository = entityRepository;
@ -35,19 +34,19 @@ public class ApiEndpointAppService : CrudAppService<
_endpointRepository = endpointRepository;
}
public virtual async Task<List<ApiEndpointDto>> GetActiveEndpointsAsync()
public virtual async Task<List<CrudEndpointDto>> GetActiveEndpointsAsync()
{
var endpoints = await Repository.GetListAsync(x => x.IsActive);
return await MapToGetListOutputDtosAsync(endpoints);
}
public virtual async Task<List<ApiEndpointDto>> GetEndpointsByEntityAsync(Guid entityId)
public virtual async Task<List<CrudEndpointDto>> GetEndpointsByEntityAsync(Guid entityId)
{
var endpoints = await _endpointRepository.GetListAsync(x => x.EntityId == entityId);
return ObjectMapper.Map<List<ApiEndpoint>, List<ApiEndpointDto>>(endpoints);
return ObjectMapper.Map<List<CrudEndpoint>, List<CrudEndpointDto>>(endpoints);
}
public virtual async Task<PagedResultDto<ApiEndpointDto>> GenerateCrudEndpointsAsync(Guid entityId)
public virtual async Task<PagedResultDto<CrudEndpointDto>> GenerateCrudEndpointsAsync(Guid entityId)
{
// Entity + Fields
var entityQueryable = await _entityRepository.GetQueryableAsync();
@ -72,60 +71,60 @@ public class ApiEndpointAppService : CrudAppService<
}
// CRUD endpointleri oluştur
var endpoints = new List<ApiEndpoint>();
var endpoints = new List<CrudEndpoint>();
var entityName = entity.Name;
var entityDisplayName = entity.DisplayName;
endpoints.Add(new ApiEndpoint
endpoints.Add(new CrudEndpoint
{
EntityId = entityId,
EntityName = entityName,
Method = "GET",
Path = $"/api/app/dynamic/{entityName.ToLower()}",
Path = $"/api/app/crudendpoint/{entityName.ToLower()}",
OperationType = "GetList",
IsActive = true,
CsharpCode = GenerateGetAllCode(entityName, entityDisplayName)
});
endpoints.Add(new ApiEndpoint
endpoints.Add(new CrudEndpoint
{
EntityId = entityId,
EntityName = entityName,
Method = "GET",
Path = $"/api/app/dynamic/{entityName.ToLower()}/{{id}}",
Path = $"/api/app/crudendpoint/{entityName.ToLower()}/{{id}}",
OperationType = "GetById",
IsActive = true,
CsharpCode = GenerateGetByIdCode(entityName, entityDisplayName)
});
endpoints.Add(new ApiEndpoint
endpoints.Add(new CrudEndpoint
{
EntityId = entityId,
EntityName = entityName,
Method = "POST",
Path = $"/api/app/dynamic/{entityName.ToLower()}",
Path = $"/api/app/crudendpoint/{entityName.ToLower()}",
OperationType = "Create",
IsActive = true,
CsharpCode = GenerateCreateCode(entityName, entityDisplayName)
});
endpoints.Add(new ApiEndpoint
endpoints.Add(new CrudEndpoint
{
EntityId = entityId,
EntityName = entityName,
Method = "PUT",
Path = $"/api/app/dynamic/{entityName.ToLower()}/{{id}}",
Path = $"/api/app/crudendpoint/{entityName.ToLower()}/{{id}}",
OperationType = "Update",
IsActive = true,
CsharpCode = GenerateUpdateCode(entityName, entityDisplayName)
});
endpoints.Add(new ApiEndpoint
endpoints.Add(new CrudEndpoint
{
EntityId = entityId,
EntityName = entityName,
Method = "DELETE",
Path = $"/api/app/dynamic/{entityName.ToLower()}/{{id}}",
Path = $"/api/app/crudendpoint/{entityName.ToLower()}/{{id}}",
OperationType = "Delete",
IsActive = true,
CsharpCode = GenerateDeleteCode(entityName, entityDisplayName)
@ -144,9 +143,9 @@ public class ApiEndpointAppService : CrudAppService<
entity.EndpointStatus = "applied";
await _entityRepository.UpdateAsync(entity, autoSave: true);
var result = ObjectMapper.Map<List<ApiEndpoint>, List<ApiEndpointDto>>(endpoints);
var result = ObjectMapper.Map<List<CrudEndpoint>, List<CrudEndpointDto>>(endpoints);
return new PagedResultDto<ApiEndpointDto>
return new PagedResultDto<CrudEndpointDto>
{
Items = result,
TotalCount = result.Count

View file

@ -14,20 +14,20 @@ using Kurs.Platform.Domain.DeveloperKit;
namespace Platform.Api.Application;
public class ApiMigrationAppService : CrudAppService<
ApiMigration,
ApiMigrationDto,
public class CrudMigrationAppService : CrudAppService<
CrudMigration,
CrudMigrationDto,
Guid,
PagedAndSortedResultRequestDto,
CreateUpdateApiMigrationDto>, IApiMigrationAppService
CreateUpdateCrudMigrationDto>, ICrudMigrationAppService
{
private readonly IRepository<ApiMigration, Guid> _migrationRepository;
private readonly IRepository<CrudMigration, Guid> _migrationRepository;
private readonly IRepository<CustomEntity, Guid> _entityRepository;
private readonly IRepository<CustomEntity, Guid> _fieldRepository;
private readonly IApiMigrationRepository _customSqlExecutor;
public ApiMigrationAppService(
IRepository<ApiMigration, Guid> migrationRepository,
public CrudMigrationAppService(
IRepository<CrudMigration, Guid> migrationRepository,
IRepository<CustomEntity, Guid> entityRepository,
IRepository<CustomEntity, Guid> fieldRepository,
IApiMigrationRepository customSqlExecutor
@ -39,7 +39,7 @@ public class ApiMigrationAppService : CrudAppService<
_customSqlExecutor = customSqlExecutor;
}
public virtual async Task<ApiMigrationDto> ApplyMigrationAsync(Guid id)
public virtual async Task<CrudMigrationDto> ApplyMigrationAsync(Guid id)
{
var migration = await _migrationRepository.GetAsync(id);
@ -57,7 +57,7 @@ public class ApiMigrationAppService : CrudAppService<
entity.MigrationStatus = "applied";
await _entityRepository.UpdateAsync(entity, autoSave: true);
return ObjectMapper.Map<ApiMigration, ApiMigrationDto>(migration);
return ObjectMapper.Map<CrudMigration, CrudMigrationDto>(migration);
}
catch (Exception ex)
{
@ -74,7 +74,7 @@ public class ApiMigrationAppService : CrudAppService<
}
public virtual async Task<List<ApiMigrationDto>> GetPendingMigrationsAsync()
public virtual async Task<List<CrudMigrationDto>> GetPendingMigrationsAsync()
{
var queryable = await _migrationRepository.GetQueryableAsync();
var pending = await queryable
@ -82,11 +82,11 @@ public class ApiMigrationAppService : CrudAppService<
.OrderBy(m => m.CreationTime)
.ToListAsync();
return ObjectMapper.Map<List<ApiMigration>, List<ApiMigrationDto>>(pending);
return ObjectMapper.Map<List<CrudMigration>, List<CrudMigrationDto>>(pending);
}
public virtual async Task<ApiMigrationDto> GenerateMigrationAsync(Guid entityId)
public virtual async Task<CrudMigrationDto> GenerateMigrationAsync(Guid entityId)
{
var queryable = await _entityRepository.GetQueryableAsync();
var entity = await queryable
@ -100,7 +100,7 @@ public class ApiMigrationAppService : CrudAppService<
var sqlScript = GenerateSqlScript(entity);
var migration = new ApiMigration
var migration = new CrudMigration
{
EntityId = entityId,
EntityName = entity.Name,
@ -115,7 +115,7 @@ public class ApiMigrationAppService : CrudAppService<
entity.MigrationStatus = "pending";
await _entityRepository.UpdateAsync(entity, autoSave: true);
return ObjectMapper.Map<ApiMigration, ApiMigrationDto>(migration);
return ObjectMapper.Map<CrudMigration, CrudMigrationDto>(migration);
}
private string GenerateSqlScript(CustomEntity entity)

View file

@ -3,7 +3,6 @@ using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Entities;
using System.Text;
using Kurs.Platform.Entities;
using Kurs.Platform.DeveloperKit;
using System;
@ -22,14 +21,14 @@ public class CustomEntityAppService : CrudAppService<
CreateUpdateCustomEntityDto>, ICustomEntityAppService
{
private readonly IRepository<CustomEntity, Guid> _repository;
private readonly IRepository<ApiMigration, Guid> _migrationRepository;
private readonly IRepository<ApiEndpoint, Guid> _endpointRepository;
private readonly IRepository<CrudMigration, Guid> _migrationRepository;
private readonly IRepository<CrudEndpoint, Guid> _endpointRepository;
private readonly IRepository<CustomEntityField, Guid> _fieldRepository;
public CustomEntityAppService(
IRepository<CustomEntity, Guid> repository,
IRepository<ApiMigration, Guid> migrationRepository,
IRepository<ApiEndpoint, Guid> endpointRepository,
IRepository<CrudMigration, Guid> migrationRepository,
IRepository<CrudEndpoint, Guid> endpointRepository,
IRepository<CustomEntityField, Guid> fieldRepository) : base(repository)
{
_repository = repository;
@ -226,7 +225,6 @@ public class CustomEntityAppService : CrudAppService<
await _migrationRepository.DeleteManyAsync(relatedMigrations);
}
// İlgili ApiEndpoint kayıtlarını sil
var relatedEndpoints = await _endpointRepository.GetListAsync(e => e.EntityId == id);
if (relatedEndpoints.Any())
{

View file

@ -20,13 +20,13 @@ public class DeveloperKitAutoMapperProfile : Profile
CreateMap<CreateUpdateCustomComponentDto, CustomComponent>();
// GeneratedEndpoint mappings
CreateMap<ApiEndpoint, ApiEndpointDto>()
CreateMap<CrudEndpoint, CrudEndpointDto>()
.ForMember(dest => dest.EntityDisplayName, opt => opt.MapFrom(src => src.Entity != null ? src.Entity.DisplayName : null));
CreateMap<CreateUpdateApiEndpointDto, ApiEndpoint>();
CreateMap<CreateUpdateCrudEndpointDto, CrudEndpoint>();
// Migration mappings
CreateMap<ApiMigration, ApiMigrationDto>();
CreateMap<CreateUpdateApiMigrationDto, ApiMigration>();
CreateMap<CrudMigration, CrudMigrationDto>();
CreateMap<CreateUpdateCrudMigrationDto, CrudMigration>();
CreateMap<DynamicService, DynamicServiceDto>()
.ForMember(dest => dest.CompilationStatus, opt => opt.MapFrom(src => src.CompilationStatus.ToString()));

View file

@ -32,7 +32,6 @@ public class DynamicServiceCompiler : ITransientDependency
private static readonly string[] ForbiddenNamespaces = {
"System.IO",
"System.Diagnostics",
"System.Threading.Thread",
"System.Environment",
"System.Net.Sockets",
"System.Reflection.Emit",
@ -46,7 +45,6 @@ public class DynamicServiceCompiler : ITransientDependency
private static readonly string[] ForbiddenTypes = {
"Process",
"ProcessStartInfo",
"Thread",
"ThreadStart",
"File",
"Directory",

View file

@ -664,26 +664,26 @@
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Entity",
"en": "Entity Management",
"tr": "Varlık Yönetimi"
"en": "Custom Entity",
"tr": "Özel Varlık"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Migrations",
"en": "Database Migrations",
"tr": "Veritabanı Geçişleri"
"en": "Crud Migrations",
"tr": "Crud Geçişleri"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Endpoints",
"en": "CRUD Endpoints",
"tr": "CRUD Uç Noktaları"
"key": "App.DeveloperKit.CrudEndpoints",
"en": "Crud Endpoints",
"tr": "Crud Uç Noktaları"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Components",
"en": "React Components",
"tr": "React Bileşenleri"
"en": "Custom Components",
"tr": "Özel Bileşenler"
},
{
"resourceName": "Platform",
@ -9535,12 +9535,6 @@
"tr": "Müşteri Yorumları",
"en": "Testimonials"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Component.Title",
"en": "React Components",
"tr": "React Bileşenleri"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Component.Description",
@ -9673,12 +9667,6 @@
"en": "Create Component",
"tr": "Bileşen Oluştur"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Endpoint.Title",
"en": "CRUD Endpoints",
"tr": "CRUD Uç Noktaları"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Endpoint.Description",
@ -9865,12 +9853,6 @@
"en": "Create some endpoints or entities to see documentation here",
"tr": "Burada dokümantasyon görmek için bazı uç noktalar veya varlıklar oluşturun"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Migration.Title",
"en": "Database Migrations",
"tr": "Veritabanı Geçişleri"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Migration.Description",
@ -10057,12 +10039,6 @@
"en": "Applied",
"tr": "Uygulandı"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Entity.Title",
"en": "Entity Management",
"tr": "Varlık Yönetimi"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Entity.Description",
@ -10255,12 +10231,6 @@
"en": "Generated APIs",
"tr": "Oluşturulan API'ler"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Dashboard.Stats.Components",
"en": "React Components",
"tr": "React Bileşenleri"
},
{
"resourceName": "Platform",
"key": "App.DeveloperKit.Dashboard.Flow.Title",

View file

@ -344,10 +344,10 @@
{
"key": "admin.developerkit.endpoints",
"path": "/admin/developerkit/endpoints",
"componentPath": "@/views/developerKit/EndpointPage",
"componentPath": "@/views/developerKit/CrudEndpointPage",
"routeType": "protected",
"authority": [
"App.DeveloperKit.Endpoints"
"App.DeveloperKit.CrudEndpoints"
]
},
{
@ -1557,12 +1557,12 @@
},
{
"ParentCode": "App.DeveloperKit",
"Code": "App.DeveloperKit.Endpoints",
"DisplayName": "App.DeveloperKit.Endpoints",
"Code": "App.DeveloperKit.CrudEndpoints",
"DisplayName": "App.DeveloperKit.CrudEndpoints",
"Order": 4,
"Url": "/admin/developerkit/endpoints",
"Icon": "FcOrgUnit",
"RequiredPermissionName": "App.DeveloperKit.Endpoints",
"RequiredPermissionName": "App.DeveloperKit.CrudEndpoints",
"IsDisabled": false
},
{
@ -1575,16 +1575,6 @@
"RequiredPermissionName": "App.DeveloperKit.CustomEndpoints",
"IsDisabled": false
},
{
"ParentCode": "App.DeveloperKit",
"Code": "App.DeveloperKit.DynamicServices",
"DisplayName": "App.DeveloperKit.DynamicServices",
"Order": 5,
"Url": "/admin/developerkit/dynamic-services",
"Icon": "FcCommandLine",
"RequiredPermissionName": "App.DeveloperKit.DynamicServices",
"IsDisabled": false
},
{
"ParentCode": "App.DeveloperKit",
"Code": "App.DeveloperKit.Components",
@ -1595,6 +1585,16 @@
"RequiredPermissionName": "App.DeveloperKit.Components",
"IsDisabled": false
},
{
"ParentCode": "App.DeveloperKit",
"Code": "App.DeveloperKit.DynamicServices",
"DisplayName": "App.DeveloperKit.DynamicServices",
"Order": 7,
"Url": "/admin/developerkit/dynamic-services",
"Icon": "FcCommandLine",
"RequiredPermissionName": "App.DeveloperKit.DynamicServices",
"IsDisabled": false
},
{
"ParentCode": "App.Administration",
"Code": "App.Reports.Management",

View file

@ -2238,9 +2238,9 @@
},
{
"GroupName": "App.Administration",
"Name": "App.DeveloperKit.Endpoints",
"Name": "App.DeveloperKit.CrudEndpoints",
"ParentName": "App.DeveloperKit",
"DisplayName": "App.DeveloperKit.Endpoints",
"DisplayName": "App.DeveloperKit.CrudEndpoints",
"IsEnabled": true,
"MultiTenancySide": 3,
"MenuGroup": "Erp|Kurs"

View file

@ -32,7 +32,7 @@ public enum TableNameEnum
CustomEntity,
CustomEntityField,
ApiMigration,
ApiEndpoint,
CrudEndpoint,
CustomEndpoint,
CustomComponent,
ReportCategory,

View file

@ -54,7 +54,7 @@ public static class TableNameResolver
{ nameof(TableNameEnum.CustomEntity), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.CustomEntityField), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.ApiMigration), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.ApiEndpoint), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.CrudEndpoint), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.CustomEndpoint), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.CustomComponent), (TablePrefix.TenantByName, MenuPrefix.Saas) },
{ nameof(TableNameEnum.ReportCategory), (TablePrefix.TenantByName, MenuPrefix.Saas) },

View file

@ -5,7 +5,7 @@ using Volo.Abp.Domain.Repositories;
namespace Kurs.Platform.Domain.DeveloperKit;
public interface IApiMigrationRepository : IRepository<ApiMigration, Guid>
public interface IApiMigrationRepository : IRepository<CrudMigration, Guid>
{
Task ExecuteSqlAsync(string sql);
}

View file

@ -4,7 +4,7 @@ using Volo.Abp.MultiTenancy;
namespace Kurs.Platform.Entities;
public class ApiEndpoint : FullAuditedEntity<Guid>, IMultiTenant
public class CrudEndpoint : FullAuditedEntity<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
@ -18,7 +18,7 @@ public class ApiEndpoint : FullAuditedEntity<Guid>, IMultiTenant
// Foreign key to CustomEntity
public Guid EntityId { get; set; }
public virtual CustomEntity Entity { get; set; } = null!;
public ApiEndpoint()
public CrudEndpoint()
{
Id = Guid.NewGuid();
}

View file

@ -4,7 +4,7 @@ using Volo.Abp.MultiTenancy;
namespace Kurs.Platform.Entities;
public class ApiMigration : AuditedEntity<Guid>, IMultiTenant
public class CrudMigration : AuditedEntity<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }

View file

@ -8,7 +8,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Platform.Domain.DeveloperKit;
public class PlatformApiMigrationRepository : EfCoreRepository<PlatformDbContext, ApiMigration, Guid>, IApiMigrationRepository
public class PlatformApiMigrationRepository : EfCoreRepository<PlatformDbContext, CrudMigration, Guid>, IApiMigrationRepository
{
public PlatformApiMigrationRepository(IDbContextProvider<PlatformDbContext> dbContextProvider)
: base(dbContextProvider)

View file

@ -60,8 +60,8 @@ public class PlatformDbContext :
public DbSet<ForumPost> ForumPosts { get; set; }
public DbSet<CustomEntity> CustomEntities { get; set; }
public DbSet<CustomEntityField> EntityFields { get; set; }
public DbSet<ApiMigration> Migrations { get; set; }
public DbSet<ApiEndpoint> GeneratedEndpoints { get; set; }
public DbSet<CrudMigration> Migrations { get; set; }
public DbSet<CrudEndpoint> GeneratedEndpoints { get; set; }
public DbSet<CustomEndpoint> CustomEndpoints { get; set; }
public DbSet<CustomComponent> CustomComponents { get; set; }
public DbSet<DynamicService> DynamicServices { get; set; }
@ -652,7 +652,7 @@ public class PlatformDbContext :
b.Property(x => x.DefaultValue).HasMaxLength(256);
});
builder.Entity<ApiMigration>(b =>
builder.Entity<CrudMigration>(b =>
{
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ApiMigration)), Prefix.DbSchema);
b.ConfigureByConvention();
@ -670,9 +670,9 @@ public class PlatformDbContext :
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<ApiEndpoint>(b =>
builder.Entity<CrudEndpoint>(b =>
{
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ApiEndpoint)), Prefix.DbSchema);
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.CrudEndpoint)), Prefix.DbSchema);
b.ConfigureByConvention();
b.HasKey(x => x.Id);

View file

@ -1,53 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Kurs.Platform.Migrations
{
/// <inheritdoc />
public partial class DynamicService : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Plat_H_DynamicService",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
Description = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
Code = table.Column<string>(type: "text", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
CompilationStatus = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
LastCompilationError = table.Column<string>(type: "text", nullable: true),
LastSuccessfulCompilation = table.Column<DateTime>(type: "datetime2", nullable: true),
Version = table.Column<int>(type: "int", nullable: false, defaultValue: 1),
CodeHash = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
PrimaryEntityType = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ControllerName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, 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_Plat_H_DynamicService", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Plat_H_DynamicService");
}
}
}

View file

@ -13,8 +13,8 @@ using Volo.Abp.EntityFrameworkCore;
namespace Kurs.Platform.Migrations
{
[DbContext(typeof(PlatformDbContext))]
[Migration("20251104205840_DynamicService")]
partial class DynamicService
[Migration("20251105082644_Initial")]
partial class Initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -802,143 +802,6 @@ namespace Kurs.Platform.Migrations
b.ToTable("Net_T_Announcement", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiEndpoint", 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<string>("CsharpCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
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>("Method")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("OperationType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_ApiEndpoint", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiMigration", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("AppliedAt")
.HasColumnType("datetime2");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ErrorMessage")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("SqlScript")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_ApiMigration", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.BackgroundWorker", b =>
{
b.Property<Guid>("Id")
@ -2681,6 +2544,143 @@ namespace Kurs.Platform.Migrations
b.ToTable("Sas_H_CountryGroup", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudEndpoint", 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<string>("CsharpCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
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>("Method")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("OperationType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_CrudEndpoint", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudMigration", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("AppliedAt")
.HasColumnType("datetime2");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ErrorMessage")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("SqlScript")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_ApiMigration", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.Currency", b =>
{
b.Property<Guid>("Id")
@ -12468,28 +12468,6 @@ namespace Kurs.Platform.Migrations
b.Navigation("Employee");
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiEndpoint", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiMigration", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.BankAccount", b =>
{
b.HasOne("Kurs.Platform.Entities.Bank", "Bank")
@ -12656,6 +12634,28 @@ namespace Kurs.Platform.Migrations
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudEndpoint", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudMigration", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.CustomEntityField", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")

View file

@ -1477,6 +1477,37 @@ namespace Kurs.Platform.Migrations
table.UniqueConstraint("AK_Plat_H_BackgroundWorker_MailQueueTableFormat_TableName", x => x.TableName);
});
migrationBuilder.CreateTable(
name: "Plat_H_DynamicService",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
DisplayName = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
Description = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: true),
Code = table.Column<string>(type: "text", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false, defaultValue: true),
CompilationStatus = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
LastCompilationError = table.Column<string>(type: "text", nullable: true),
LastSuccessfulCompilation = table.Column<DateTime>(type: "datetime2", nullable: true),
Version = table.Column<int>(type: "int", nullable: false, defaultValue: 1),
CodeHash = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
PrimaryEntityType = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ControllerName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, 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_Plat_H_DynamicService", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Plat_H_Language",
columns: table => new
@ -3405,38 +3436,6 @@ namespace Kurs.Platform.Migrations
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "Sas_T_ApiEndpoint",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EntityName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Method = table.Column<string>(type: "nvarchar(10)", maxLength: 10, nullable: false),
Path = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
OperationType = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
CsharpCode = table.Column<string>(type: "nvarchar(max)", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
EntityId = table.Column<Guid>(type: "uniqueidentifier", 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_Sas_T_ApiEndpoint", x => x.Id);
table.ForeignKey(
name: "FK_Sas_T_ApiEndpoint_Sas_T_CustomEntity_EntityId",
column: x => x.EntityId,
principalTable: "Sas_T_CustomEntity",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Sas_T_ApiMigration",
columns: table => new
@ -3466,6 +3465,38 @@ namespace Kurs.Platform.Migrations
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "Sas_T_CrudEndpoint",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
EntityName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Method = table.Column<string>(type: "nvarchar(10)", maxLength: 10, nullable: false),
Path = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
OperationType = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
CsharpCode = table.Column<string>(type: "nvarchar(max)", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
EntityId = table.Column<Guid>(type: "uniqueidentifier", 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_Sas_T_CrudEndpoint", x => x.Id);
table.ForeignKey(
name: "FK_Sas_T_CrudEndpoint_Sas_T_CustomEntity_EntityId",
column: x => x.EntityId,
principalTable: "Sas_T_CustomEntity",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Sas_T_CustomEntityField",
columns: table => new
@ -5989,11 +6020,6 @@ namespace Kurs.Platform.Migrations
column: "Key",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Sas_T_ApiEndpoint_EntityId",
table: "Sas_T_ApiEndpoint",
column: "EntityId");
migrationBuilder.CreateIndex(
name: "IX_Sas_T_ApiMigration_EntityId",
table: "Sas_T_ApiMigration",
@ -6004,6 +6030,11 @@ namespace Kurs.Platform.Migrations
table: "Sas_T_BranchUsers",
column: "BranchId");
migrationBuilder.CreateIndex(
name: "IX_Sas_T_CrudEndpoint_EntityId",
table: "Sas_T_CrudEndpoint",
column: "EntityId");
migrationBuilder.CreateIndex(
name: "IX_Sas_T_CustomEntityField_EntityId",
table: "Sas_T_CustomEntityField",
@ -6339,6 +6370,9 @@ namespace Kurs.Platform.Migrations
migrationBuilder.DropTable(
name: "Plat_H_BackgroundWorker_MailQueueEvents");
migrationBuilder.DropTable(
name: "Plat_H_DynamicService");
migrationBuilder.DropTable(
name: "Plat_H_LanguageText");
@ -6402,15 +6436,15 @@ namespace Kurs.Platform.Migrations
migrationBuilder.DropTable(
name: "Sas_T_Activity");
migrationBuilder.DropTable(
name: "Sas_T_ApiEndpoint");
migrationBuilder.DropTable(
name: "Sas_T_ApiMigration");
migrationBuilder.DropTable(
name: "Sas_T_BranchUsers");
migrationBuilder.DropTable(
name: "Sas_T_CrudEndpoint");
migrationBuilder.DropTable(
name: "Sas_T_CustomComponent");

View file

@ -799,143 +799,6 @@ namespace Kurs.Platform.Migrations
b.ToTable("Net_T_Announcement", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiEndpoint", 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<string>("CsharpCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
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>("Method")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("OperationType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_ApiEndpoint", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiMigration", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("AppliedAt")
.HasColumnType("datetime2");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ErrorMessage")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("SqlScript")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_ApiMigration", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.BackgroundWorker", b =>
{
b.Property<Guid>("Id")
@ -2678,6 +2541,143 @@ namespace Kurs.Platform.Migrations
b.ToTable("Sas_H_CountryGroup", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudEndpoint", 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<string>("CsharpCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("DeleterId")
.HasColumnType("uniqueidentifier")
.HasColumnName("DeleterId");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2")
.HasColumnName("DeletionTime");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
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>("Method")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.Property<string>("OperationType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Path")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_CrudEndpoint", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudMigration", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("AppliedAt")
.HasColumnType("datetime2");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("uniqueidentifier")
.HasColumnName("CreatorId");
b.Property<Guid>("EntityId")
.HasColumnType("uniqueidentifier");
b.Property<string>("EntityName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ErrorMessage")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("FileName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime2")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("uniqueidentifier")
.HasColumnName("LastModifierId");
b.Property<string>("SqlScript")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("EntityId");
b.ToTable("Sas_T_ApiMigration", (string)null);
});
modelBuilder.Entity("Kurs.Platform.Entities.Currency", b =>
{
b.Property<Guid>("Id")
@ -12465,28 +12465,6 @@ namespace Kurs.Platform.Migrations
b.Navigation("Employee");
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiEndpoint", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.ApiMigration", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.BankAccount", b =>
{
b.HasOne("Kurs.Platform.Entities.Bank", "Bank")
@ -12653,6 +12631,28 @@ namespace Kurs.Platform.Migrations
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudEndpoint", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.CrudMigration", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")
.WithMany()
.HasForeignKey("EntityId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Entity");
});
modelBuilder.Entity("Kurs.Platform.Entities.CustomEntityField", b =>
{
b.HasOne("Kurs.Platform.Entities.CustomEntity", "Entity")

View file

@ -88,7 +88,7 @@
"CustomComponents": [
{
"name": "DynamicEntityComponent",
"code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\", // defaults'ı her seferinde set etme\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/dynamic/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white border border-slate-200 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 text-sm font-medium text-slate-700\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={rowIndex} className=\"hover:bg-slate-50\">\n <td className=\"px-4 py-2 border-b border-slate-100 text-sm text-slate-800\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 text-sm text-slate-800\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100\">\n <button\n onClick={() => alert(item.name)}\n className=\"bg-blue-600 hover:bg-blue-700 text-white text-sm px-3 py-1 rounded-lg shadow-sm transition\"\n >\n Show Name\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
"code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344\", // defaults'ı her seferinde set etme\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white border border-slate-200 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 text-sm font-medium text-slate-700\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={rowIndex} className=\"hover:bg-slate-50\">\n <td className=\"px-4 py-2 border-b border-slate-100 text-sm text-slate-800\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 text-sm text-slate-800\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100\">\n <button\n onClick={() => alert(item.name)}\n className=\"bg-blue-600 hover:bg-blue-700 text-white text-sm px-3 py-1 rounded-lg shadow-sm transition\"\n >\n Show Name\n </button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
"props": null,
"description": null,
"isActive": true,

View file

@ -92,7 +92,7 @@ const ComponentManager: React.FC = () => {
<div className="flex items-center justify-between mb-4">
<div>
<h1 className="text-2xl font-bold text-slate-900">
{translate('::App.DeveloperKit.Component.Title')}
{translate('::App.DeveloperKit.Component')}
</h1>
<p className="text-slate-600">{translate('::App.DeveloperKit.Component.Description')}</p>
</div>

View file

@ -45,7 +45,7 @@ interface ParameterInput {
description?: string
}
const EndpointManager: React.FC = () => {
const CrudEndpointManager: React.FC = () => {
const { generatedEndpoints } = useEntities()
const { translate } = useLocalization()
@ -271,8 +271,8 @@ const EndpointManager: React.FC = () => {
const method = endpoint.method
let data = null
// For generated endpoints, use the Dynamic API
url = `${import.meta.env.VITE_API_URL}/api/app/Dynamic/${endpoint.entityName}`
// For generated endpoints, use the Crud API
url = `${import.meta.env.VITE_API_URL}/api/app/crudendpoint/${endpoint.entityName}`
// Get parameters and modify URL based on operation type
const parameters = getEndpointParameters(endpoint)
@ -370,7 +370,7 @@ const EndpointManager: React.FC = () => {
<div className="flex items-center justify-between mb-4">
<div>
<h1 className="text-2xl font-bold text-slate-900">
{translate('::App.DeveloperKit.Endpoint.Title')}
{translate('::App.DeveloperKit.CrudEndpoints')}
</h1>
<p className="text-slate-600">{translate('::App.DeveloperKit.Endpoint.Description')}</p>
</div>
@ -791,4 +791,4 @@ const EndpointManager: React.FC = () => {
)
}
export default EndpointManager
export default CrudEndpointManager

View file

@ -55,7 +55,7 @@ const Dashboard: React.FC = () => {
href: ROUTES_ENUM.protected.saas.developerKit.endpoints,
},
{
name: translate('::App.DeveloperKit.Dashboard.Stats.Components'),
name: translate('::App.DeveloperKit.Components'),
value: components?.filter((c) => c.isActive).length,
total: components?.length,
icon: FaPuzzlePiece,

View file

@ -16,7 +16,7 @@ import { ROUTES_ENUM } from '@/routes/route.constant'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Formik, Form, Field, FieldProps, FieldArray } from 'formik'
import * as Yup from 'yup'
import { FormItem, Input, Select, Checkbox, FormContainer } from '@/components/ui'
import { FormItem, Input, Select, Checkbox, FormContainer, Button } from '@/components/ui'
import { SelectBoxOption } from '@/shared/types'
// Validation schema
@ -152,12 +152,12 @@ const EntityEditor: React.FC = () => {
}
const fieldTypes = [
{ value: 'string', label: 'String (Text)' },
{ value: 'number', label: 'Number (Integer)' },
{ value: 'string', label: 'String' },
{ value: 'number', label: 'Number' },
{ value: 'decimal', label: 'Decimal' },
{ value: 'boolean', label: 'Boolean (True/False)' },
{ value: 'boolean', label: 'Boolean' },
{ value: 'date', label: 'Date' },
{ value: 'guid', label: 'GUID (Unique ID)' },
{ value: 'guid', label: 'Guid' },
]
return (
@ -218,7 +218,7 @@ const EntityEditor: React.FC = () => {
</div>
</div>
<Form className="grid grid-cols-1 lg:grid-cols-3 gap-4 pt-2">
<Form className="grid grid-cols-1 lg:grid-cols-4 gap-4 pt-2">
{/* Basic Entity Information */}
<div className="space-y-4 col-span-1">
<div className="bg-white rounded-lg shadow-sm border border-slate-200 p-3">
@ -309,7 +309,7 @@ const EntityEditor: React.FC = () => {
</div>
{/* Fields Section */}
<div className="space-y-4 col-span-2">
<div className="space-y-4 col-span-3">
<div className="bg-white rounded-lg shadow-sm border border-slate-200 p-3">
<FormContainer size="sm">
<FieldArray name="fields">
@ -345,15 +345,50 @@ const EntityEditor: React.FC = () => {
</button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-2 mb-2">
<div className="col-span-1">Order *</div>
<div className="col-span-2 font-bold">
{translate('::App.DeveloperKit.EntityEditor.FieldName')} *
</div>
<div className="col-span-1 font-bold">
{translate('::App.DeveloperKit.EntityEditor.Type')} *
</div>
<div className="col-span-2 font-bold">
{translate('::App.DeveloperKit.EntityEditor.DefaultValue')}
</div>
<div className="font-bold">
{translate('::App.DeveloperKit.EntityEditor.MaxLength')}
</div>
<div className="col-span-2 font-bold">
{translate('::App.DeveloperKit.EntityEditor.Description')}
</div>
<div className="items-center font-bold">
{translate('::App.DeveloperKit.EntityEditor.Required')}
</div>
<div className="items-center font-bold">
{translate('::App.DeveloperKit.EntityEditor.Unique')}
</div>
</div>
{values.fields.map((field, index) => (
<div key={field.id || `new-${index}`}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-2 mb-2">
<FormItem label="Order *" className="col-span-1">
<Field type="number" name={`fields.${index}.displayOrder`} component={Input} />
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-2">
<FormItem className="col-span-1">
<Field
type="number"
name={`fields.${index}.displayOrder`}
component={Input}
/>
</FormItem>
<FormItem
label={`${translate('::App.DeveloperKit.EntityEditor.FieldName')} *`}
invalid={
!!(
errors.fields &&
@ -373,7 +408,6 @@ const EntityEditor: React.FC = () => {
</FormItem>
<FormItem
label={`${translate('::App.DeveloperKit.EntityEditor.Type')} *`}
invalid={
!!(
errors.fields &&
@ -406,7 +440,6 @@ const EntityEditor: React.FC = () => {
</FormItem>
<FormItem
label={translate('::App.DeveloperKit.EntityEditor.DefaultValue')}
invalid={
!!(
errors.fields &&
@ -427,32 +460,27 @@ const EntityEditor: React.FC = () => {
/>
</FormItem>
{field.type === 'string' && (
<FormItem
label={translate('::App.DeveloperKit.EntityEditor.MaxLength')}
invalid={
!!(
errors.fields &&
(errors.fields as any)[index]?.maxLength &&
touched.fields &&
(touched.fields as any)[index]?.maxLength
)
}
errorMessage={
(errors.fields as any)?.[index]?.maxLength as string
}
>
<Field
name={`fields.${index}.maxLength`}
component={Input}
type="number"
placeholder="e.g., 100"
/>
</FormItem>
)}
<FormItem
invalid={
!!(
errors.fields &&
(errors.fields as any)[index]?.maxLength &&
touched.fields &&
(touched.fields as any)[index]?.maxLength
)
}
errorMessage={(errors.fields as any)?.[index]?.maxLength as string}
>
<Field
name={`fields.${index}.maxLength`}
component={Input}
type="number"
placeholder="e.g., 100"
disabled={field.type !== 'string'}
/>
</FormItem>
<FormItem
label={translate('::App.DeveloperKit.EntityEditor.Description')}
invalid={
!!(
errors.fields &&
@ -464,7 +492,7 @@ const EntityEditor: React.FC = () => {
errorMessage={
(errors.fields as any)?.[index]?.description as string
}
className={field.type === 'string' ? 'col-span-2' : 'col-span-3'}
className="col-span-2"
>
<Field
name={`fields.${index}.description`}
@ -473,38 +501,30 @@ const EntityEditor: React.FC = () => {
/>
</FormItem>
<FormItem
label={translate('::App.DeveloperKit.EntityEditor.Required')}
className="items-center"
>
<FormItem className="items-center">
<Field name={`fields.${index}.isRequired`} component={Checkbox} />
</FormItem>
<FormItem
label={translate('::App.DeveloperKit.EntityEditor.Unique')}
className="items-center"
>
<FormItem className="items-center">
<Field name={`fields.${index}.isUnique`} component={Checkbox} />
</FormItem>
<button
type="button"
<Button
size="xs"
onClick={() => {
// Remove the field and reindex displayOrder for remaining fields
remove(index)
const newFields = values.fields ? [...values.fields] : []
newFields.splice(index, 1)
newFields.forEach((f, i) => {
// ensure sequential ordering starting at 1
f.displayOrder = i + 1
})
setFieldValue('fields', newFields)
}}
className="p-3 text-red-600 hover:text-red-800 rounded transition-all duration-200"
className="!px-0 !py-0 !border-0 text-red-600 hover:text-red-800 rounded transition-all duration-200"
title="Remove field"
>
<FaTrashAlt className="w-5 h-5" />
</button>
</Button>
</div>
</div>
))}

View file

@ -89,7 +89,7 @@ const EntityManager: React.FC = () => {
<div className="flex items-center justify-between mb-4">
<div>
<h1 className="text-2xl font-bold text-slate-900">
{translate('::App.DeveloperKit.Entity.Title')}
{translate('::App.DeveloperKit.Entity')}
</h1>
<p className="text-slate-600">{translate('::App.DeveloperKit.Entity.Description')}</p>
</div>

View file

@ -163,7 +163,7 @@ const MigrationManager: React.FC = () => {
<div className="flex items-center justify-between mb-4">
<div>
<h1 className="text-xl font-bold text-slate-900 mb-2">
{translate('::App.DeveloperKit.Migration.Title')}
{translate('::App.DeveloperKit.Migration')}
</h1>
<p className="text-slate-600">{translate('::App.DeveloperKit.Migration.Description')}</p>
</div>

View file

@ -35,7 +35,7 @@ const DeveloperLayout: React.FC<DeveloperLayoutProps> = ({ children }) => {
},
{
id: 'endpoints',
label: translate('::App.DeveloperKit.Endpoints'),
label: translate('::App.DeveloperKit.CrudEndpoints'),
icon: FaServer,
path: ROUTES_ENUM.protected.saas.developerKit.endpoints,
},

View file

@ -2,7 +2,7 @@ import React, { createContext, useContext, useState, useEffect } from "react";
import {
developerKitService,
} from "@/services/developerKit.service";
import { ApiEndpoint, ApiMigration, CreateUpdateCustomEntityDto, CustomEntity } from "@/proxy/developerKit/models";
import { CrudEndpoint, ApiMigration, CreateUpdateCustomEntityDto, CustomEntity } from "@/proxy/developerKit/models";
export const FIELD_TYPE_OPTIONS = [
{ label: "String", value: "string" },
@ -18,7 +18,7 @@ export type EntityFieldType = (typeof FIELD_TYPE_OPTIONS)[number]["value"];
interface EntityContextType {
entities: CustomEntity[];
migrations: ApiMigration[];
generatedEndpoints: ApiEndpoint[];
generatedEndpoints: CrudEndpoint[];
loading: boolean;
error: string | null;
// Entity operations
@ -36,7 +36,7 @@ interface EntityContextType {
// Generated endpoint operations
generateCrudEndpoints: (entityId: string) => Promise<void>;
toggleEndpoint: (endpointId: string) => Promise<void>;
getEntityEndpoints: (entityId: string) => ApiEndpoint[];
getEntityEndpoints: (entityId: string) => CrudEndpoint[];
deleteGeneratedEndpoint: (id: string) => Promise<void>;
}
@ -59,7 +59,7 @@ export const EntityProvider: React.FC<{ children: React.ReactNode }> = ({
const [error, setError] = useState<string | null>(null);
const [migrations, setMigrations] = useState<ApiMigration[]>([]);
const [generatedEndpoints, setGeneratedEndpoints] = useState<ApiEndpoint[]>([]);
const [generatedEndpoints, setGeneratedEndpoints] = useState<CrudEndpoint[]>([]);
const refreshEntities = async () => {
try {
@ -257,7 +257,7 @@ export const EntityProvider: React.FC<{ children: React.ReactNode }> = ({
}
};
const getEntityEndpoints = (entityId: string): ApiEndpoint[] => {
const getEntityEndpoints = (entityId: string): CrudEndpoint[] => {
return generatedEndpoints.filter((endpoint) => endpoint.entityId === entityId);
};

View file

@ -53,7 +53,7 @@ export interface CreateUpdateCustomEntityDto {
fields: CreateUpdateCustomEntityFieldDto[];
}
export interface ApiEndpoint {
export interface CrudEndpoint {
id: string;
entityId: string;
entityName: string;
@ -66,7 +66,7 @@ export interface ApiEndpoint {
lastModificationTime?: string;
}
export interface CreateUpdateApiEndpointDto {
export interface CreateUpdateCrudEndpointDto {
entityId: string;
entityName: string;
method: "GET" | "POST" | "PUT" | "DELETE";

View file

@ -1,9 +1,9 @@
import { PagedResultDto } from '@/proxy'
import apiService from './api.service'
import {
ApiEndpoint,
CrudEndpoint,
ApiMigration,
CreateUpdateApiEndpointDto,
CreateUpdateCrudEndpointDto,
CreateUpdateApiMigrationDto,
CreateUpdateCustomComponentDto,
CreateUpdateCustomEntityDto,
@ -125,7 +125,7 @@ class DeveloperKitService {
// Migration endpoints
async getMigrations(): Promise<PagedResultDto<ApiMigration>> {
const response = await apiService.fetchData<PagedResultDto<ApiMigration>>({
url: '/api/app/api-migration',
url: '/api/app/crud-migration',
method: 'GET',
})
return response.data
@ -133,7 +133,7 @@ class DeveloperKitService {
async getMigration(id: string): Promise<ApiMigration> {
const response = await apiService.fetchData<ApiMigration>({
url: `/api/app/api-migration/${id}`,
url: `/api/app/crud-migration/${id}`,
method: 'GET',
})
return response.data
@ -141,7 +141,7 @@ class DeveloperKitService {
async createMigration(data: CreateUpdateApiMigrationDto): Promise<ApiMigration> {
const response = await apiService.fetchData<ApiMigration>({
url: '/api/app/api-migration',
url: '/api/app/crud-migration',
method: 'POST',
data: data as any,
})
@ -150,7 +150,7 @@ class DeveloperKitService {
async updateMigration(id: string, data: CreateUpdateApiMigrationDto): Promise<ApiMigration> {
const response = await apiService.fetchData<ApiMigration>({
url: `/api/app/api-migration/${id}`,
url: `/api/app/crud-migration/${id}`,
method: 'PUT',
data: data as any,
})
@ -159,14 +159,14 @@ class DeveloperKitService {
async deleteMigration(id: string): Promise<void> {
await apiService.fetchData<void>({
url: `/api/app/api-migration/${id}`,
url: `/api/app/crud-migration/${id}`,
method: 'DELETE',
})
}
async applyMigration(id: string): Promise<ApiMigration> {
const response = await apiService.fetchData<ApiMigration>({
url: `/api/app/api-migration/${id}/apply-migration`,
url: `/api/app/crud-migration/${id}/apply-migration`,
method: 'POST',
})
return response.data
@ -174,7 +174,7 @@ class DeveloperKitService {
async getPendingMigrations(): Promise<PagedResultDto<ApiMigration>> {
const response = await apiService.fetchData<PagedResultDto<ApiMigration>>({
url: '/api/app/api-migration/pending-migrations',
url: '/api/app/crud-migration/pending-migrations',
method: 'GET',
})
return response.data
@ -182,48 +182,48 @@ class DeveloperKitService {
async generateMigration(entityId: string): Promise<ApiMigration> {
const response = await apiService.fetchData<ApiMigration>({
url: `/api/app/api-migration/generate-migration/${entityId}`,
url: `/api/app/crud-migration/generate-migration/${entityId}`,
method: 'POST',
})
return response.data
}
// Generated Endpoint endpoints
async getGeneratedEndpoints(): Promise<PagedResultDto<ApiEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<ApiEndpoint>>({
url: '/api/app/api-endpoint',
async getGeneratedEndpoints(): Promise<PagedResultDto<CrudEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<CrudEndpoint>>({
url: '/api/app/crud-endpoint-generate',
method: 'GET',
})
return response.data
}
async getActiveGeneratedEndpoints(): Promise<PagedResultDto<ApiEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<ApiEndpoint>>({
url: '/api/app/api-endpoint/active-endpoints',
async getActiveGeneratedEndpoints(): Promise<PagedResultDto<CrudEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<CrudEndpoint>>({
url: '/api/app/crud-endpoint-generate/active-endpoints',
method: 'GET',
})
return response.data
}
async getEndpointsByEntity(entityId: string): Promise<PagedResultDto<ApiEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<ApiEndpoint>>({
url: `/api/app/api-endpoint/endpoints-by-entity/${entityId}`,
async getEndpointsByEntity(entityId: string): Promise<PagedResultDto<CrudEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<CrudEndpoint>>({
url: `/api/app/crud-endpoint-generate/endpoints-by-entity/${entityId}`,
method: 'GET',
})
return response.data
}
async getGeneratedEndpoint(id: string): Promise<ApiEndpoint> {
const response = await apiService.fetchData<ApiEndpoint>({
url: `/api/app/api-endpoint/${id}`,
async getGeneratedEndpoint(id: string): Promise<CrudEndpoint> {
const response = await apiService.fetchData<CrudEndpoint>({
url: `/api/app/crud-endpoint-generate/${id}`,
method: 'GET',
})
return response.data
}
async createGeneratedEndpoint(data: CreateUpdateApiEndpointDto): Promise<ApiEndpoint> {
const response = await apiService.fetchData<ApiEndpoint>({
url: '/api/app/api-endpoint',
async createGeneratedEndpoint(data: CreateUpdateCrudEndpointDto): Promise<CrudEndpoint> {
const response = await apiService.fetchData<CrudEndpoint>({
url: '/api/app/crud-endpoint-generate',
method: 'POST',
data: data as any,
})
@ -232,10 +232,10 @@ class DeveloperKitService {
async updateGeneratedEndpoint(
id: string,
endpoint: CreateUpdateApiEndpointDto,
): Promise<ApiEndpoint> {
const response = await apiService.fetchData<ApiEndpoint>({
url: `/api/app/api-endpoint/${id}`,
endpoint: CreateUpdateCrudEndpointDto,
): Promise<CrudEndpoint> {
const response = await apiService.fetchData<CrudEndpoint>({
url: `/api/app/crud-endpoint-generate/${id}`,
method: 'PUT',
data: endpoint as any,
})
@ -244,22 +244,22 @@ class DeveloperKitService {
async deleteGeneratedEndpoint(id: string): Promise<void> {
await apiService.fetchData<void>({
url: `/api/app/api-endpoint/${id}`,
url: `/api/app/crud-endpoint-generate/${id}`,
method: 'DELETE',
})
}
async toggleGeneratedEndpoint(id: string): Promise<ApiEndpoint> {
const response = await apiService.fetchData<ApiEndpoint>({
url: `/api/app/api-endpoint/${id}/toggle`,
async toggleGeneratedEndpoint(id: string): Promise<CrudEndpoint> {
const response = await apiService.fetchData<CrudEndpoint>({
url: `/api/app/crud-endpoint-generate/${id}/toggle`,
method: 'POST',
})
return response.data
}
async generateCrudEndpoints(entityId: string): Promise<PagedResultDto<ApiEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<ApiEndpoint>>({
url: `/api/app/api-endpoint/generate-crud-endpoints/${entityId}`,
async generateCrudEndpoints(entityId: string): Promise<PagedResultDto<CrudEndpoint>> {
const response = await apiService.fetchData<PagedResultDto<CrudEndpoint>>({
url: `/api/app/crud-endpoint-generate/generate-crud-endpoints/${entityId}`,
method: 'POST',
})
return response.data

View file

@ -1,5 +1,6 @@
import { ApiMigration, CrudEndpoint, CustomEntity } from '@/proxy/developerKit/models';
import { developerKitService } from '@/services/developerKit.service';
import { useState, useEffect } from 'react';
import { developerKitService, CustomEntity, ApiMigration, ApiEndpoint } from '../../services/developerKit.service';
export const useEntities = () => {
const [entities, setEntities] = useState<CustomEntity[]>([]);
@ -62,7 +63,7 @@ export const useMigrations = () => {
};
export const useGeneratedEndpoints = () => {
const [endpoints, setEndpoints] = useState<ApiEndpoint[]>([]);
const [endpoints, setEndpoints] = useState<CrudEndpoint[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

View file

@ -1,16 +1,16 @@
import React from 'react'
import { EntityProvider } from '@/contexts/EntityContext'
import DeveloperLayout from '@/components/layouts/DeveloperLayout'
import EndpointManager from '@/components/developerKit/EndpointManager'
import CrudEndpointManager from '@/components/developerKit/CrudEndpointManager'
const EndpointPage: React.FC = () => {
const CrudEndpointPage: React.FC = () => {
return (
<DeveloperLayout>
<EntityProvider>
<EndpointManager />
<CrudEndpointManager />
</EntityProvider>
</DeveloperLayout>
)
}
export default EndpointPage
export default CrudEndpointPage