Html Report Definition
This commit is contained in:
parent
7d9705951d
commit
7738a34a55
38 changed files with 418 additions and 3452 deletions
|
|
@ -1,37 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class CreateReportTemplateDto
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string HtmlContent { get; set; }
|
|
||||||
public Guid CategoryId { get; set; }
|
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
public List<CreateReportParameterDto> Parameters { get; set; }
|
|
||||||
|
|
||||||
public CreateReportTemplateDto()
|
|
||||||
{
|
|
||||||
Tags = [];
|
|
||||||
Parameters = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CreateReportParameterDto
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Placeholder { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string DefaultValue { get; set; }
|
|
||||||
public bool Required { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
using System;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class GetReportTemplatesInput : PagedAndSortedResultRequestDto
|
|
||||||
{
|
|
||||||
public string Filter { get; set; }
|
|
||||||
public Guid CategoryId { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GetGeneratedReportsInput : PagedAndSortedResultRequestDto
|
|
||||||
{
|
|
||||||
public string Filter { get; set; }
|
|
||||||
public Guid? TemplateId { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
using Volo.Abp.Application.Services;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public interface IReportAppService : IApplicationService
|
|
||||||
{
|
|
||||||
// Template operations
|
|
||||||
Task<PagedResultDto<ReportTemplateDto>> GetTemplatesAsync(GetReportTemplatesInput input);
|
|
||||||
Task<ReportTemplateDto> GetTemplateAsync(Guid id);
|
|
||||||
Task<ReportTemplateDto> CreateTemplateAsync(CreateReportTemplateDto input);
|
|
||||||
Task<ReportTemplateDto> UpdateTemplateAsync(Guid id, UpdateReportTemplateDto input);
|
|
||||||
Task DeleteTemplateAsync(Guid id);
|
|
||||||
|
|
||||||
// Generated Report operations
|
|
||||||
Task<PagedResultDto<ReportGeneratedDto>> GetGeneratedReportsAsync(GetGeneratedReportsInput input);
|
|
||||||
Task<ReportGeneratedDto> GetGeneratedReportAsync(Guid id);
|
|
||||||
Task<ReportGeneratedDto> GenerateReportAsync(ReportGenerateDto input);
|
|
||||||
Task DeleteGeneratedReportAsync(Guid id);
|
|
||||||
|
|
||||||
// Bulk operations
|
|
||||||
Task<ReportsDataDto> GetAllDataAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ReportsDataDto
|
|
||||||
{
|
|
||||||
public PagedResultDto<ReportTemplateDto> Templates { get; set; }
|
|
||||||
public PagedResultDto<ReportGeneratedDto> GeneratedReports { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
using System;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class ReportCategoryDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public string Icon { get; set; }
|
|
||||||
|
|
||||||
public int TemplateCount { get; init; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class ReportGenerateDto
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public Guid TemplateId { get; set; }
|
|
||||||
|
|
||||||
public Dictionary<string, string> Parameters { get; set; }
|
|
||||||
|
|
||||||
public ReportGenerateDto()
|
|
||||||
{
|
|
||||||
Parameters = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class ReportGeneratedDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
public Guid? TemplateId { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string TemplateName { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string GeneratedContent { get; set; }
|
|
||||||
public Dictionary<string, string> Parameters { get; set; }
|
|
||||||
|
|
||||||
public ReportTemplateDto ReportTemplate { get; set; }
|
|
||||||
|
|
||||||
public ReportGeneratedDto()
|
|
||||||
{
|
|
||||||
Parameters = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class ReportParameterDto
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
public Guid? TemplateId { get; set; }
|
|
||||||
[Required]
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Placeholder { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string DefaultValue { get; set; }
|
|
||||||
public bool Required { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class ReportTemplateDto : FullAuditedEntityDto<Guid>
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string HtmlContent { get; set; }
|
|
||||||
public Guid CategoryId { get; set; }
|
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
|
|
||||||
public List<ReportParameterDto> Parameters { get; set; }
|
|
||||||
|
|
||||||
public ReportTemplateDto()
|
|
||||||
{
|
|
||||||
Tags = [];
|
|
||||||
Parameters = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports;
|
|
||||||
|
|
||||||
public class UpdateReportTemplateDto
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string HtmlContent { get; set; }
|
|
||||||
public Guid CategoryId { get; set; }
|
|
||||||
public List<string> Tags { get; set; }
|
|
||||||
public List<UpdateReportParameterDto> Parameters { get; set; }
|
|
||||||
|
|
||||||
public UpdateReportTemplateDto()
|
|
||||||
{
|
|
||||||
Tags = [];
|
|
||||||
Parameters = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateReportParameterDto
|
|
||||||
{
|
|
||||||
public Guid? Id { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Placeholder { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string DefaultValue { get; set; }
|
|
||||||
public bool Required { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,408 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Erp.Platform.Entities;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Volo.Abp.Application.Dtos;
|
|
||||||
using Volo.Abp.Domain.Repositories;
|
|
||||||
using System.Linq.Dynamic.Core;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports;
|
|
||||||
|
|
||||||
[Authorize()]
|
|
||||||
public class ReportAppService : PlatformAppService, IReportAppService
|
|
||||||
{
|
|
||||||
private readonly IRepository<ReportTemplate, Guid> _reportTemplateRepository;
|
|
||||||
private readonly IRepository<ReportGenerated, Guid> _generatedReportRepository;
|
|
||||||
private readonly IRepository<ReportParameter, Guid> _reportParameterRepository;
|
|
||||||
private readonly IRepository<ReportCategory, Guid> _reportCategotyRepository;
|
|
||||||
|
|
||||||
public ReportAppService(
|
|
||||||
IRepository<ReportTemplate, Guid> reportTemplateRepository,
|
|
||||||
IRepository<ReportGenerated, Guid> generatedReportRepository,
|
|
||||||
IRepository<ReportParameter, Guid> reportParameterRepository,
|
|
||||||
IRepository<ReportCategory, Guid> reportCategotyRepository
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_reportTemplateRepository = reportTemplateRepository;
|
|
||||||
_generatedReportRepository = generatedReportRepository;
|
|
||||||
_reportParameterRepository = reportParameterRepository;
|
|
||||||
_reportCategotyRepository = reportCategotyRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<List<ReportCategoryDto>> GetCategoriesAsync()
|
|
||||||
{
|
|
||||||
var entity = await _reportCategotyRepository.GetListAsync();
|
|
||||||
|
|
||||||
return ObjectMapper.Map<List<ReportCategory>, List<ReportCategoryDto>>(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PagedResultDto<ReportTemplateDto>> GetTemplatesAsync(GetReportTemplatesInput input)
|
|
||||||
{
|
|
||||||
// IQueryable başlat - Parameters'ı include et
|
|
||||||
var query = await _reportTemplateRepository.GetQueryableAsync();
|
|
||||||
query = query.Include(x => x.Parameters);
|
|
||||||
|
|
||||||
// Filtreleme
|
|
||||||
if (!string.IsNullOrWhiteSpace(input.Filter))
|
|
||||||
{
|
|
||||||
query = query.Where(x =>
|
|
||||||
x.Name.Contains(input.Filter) ||
|
|
||||||
x.Description.Contains(input.Filter)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.CategoryId != Guid.Empty)
|
|
||||||
{
|
|
||||||
query = query.Where(x => x.CategoryId == input.CategoryId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toplam kayıt sayısı
|
|
||||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
|
||||||
|
|
||||||
// Sıralama (ABP default olarak sorting null ise Id'ye göre sıralar)
|
|
||||||
query = query.OrderBy(input.Sorting ?? nameof(ReportTemplate.Name));
|
|
||||||
|
|
||||||
// Sayfalama
|
|
||||||
var templates = await AsyncExecuter.ToListAsync(
|
|
||||||
query
|
|
||||||
.Skip(input.SkipCount)
|
|
||||||
.Take(input.MaxResultCount)
|
|
||||||
);
|
|
||||||
|
|
||||||
// DTO dönüşümü
|
|
||||||
var templateDtos = templates.Select(MapToReportTemplateDto).ToList();
|
|
||||||
|
|
||||||
return new PagedResultDto<ReportTemplateDto>(
|
|
||||||
totalCount,
|
|
||||||
templateDtos
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ReportTemplateDto> GetTemplateAsync(Guid id)
|
|
||||||
{
|
|
||||||
var query = await _reportTemplateRepository.GetQueryableAsync();
|
|
||||||
var template = await query
|
|
||||||
.Include(x => x.Parameters)
|
|
||||||
.FirstOrDefaultAsync(x => x.Id == id);
|
|
||||||
|
|
||||||
if (template == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Template with id {id} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
return MapToReportTemplateDto(template);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ReportTemplateDto> CreateTemplateAsync(CreateReportTemplateDto input)
|
|
||||||
{
|
|
||||||
var template = new ReportTemplate(
|
|
||||||
GuidGenerator.Create(),
|
|
||||||
input.Name,
|
|
||||||
input.Description,
|
|
||||||
input.HtmlContent,
|
|
||||||
input.CategoryId)
|
|
||||||
{
|
|
||||||
Tags = JsonSerializer.Serialize(input.Tags)
|
|
||||||
};
|
|
||||||
|
|
||||||
template = await _reportTemplateRepository.InsertAsync(template, true);
|
|
||||||
|
|
||||||
// Parameters ekle
|
|
||||||
foreach (var paramDto in input.Parameters)
|
|
||||||
{
|
|
||||||
var parameter = new ReportParameter(
|
|
||||||
GuidGenerator.Create(),
|
|
||||||
template.Id,
|
|
||||||
paramDto.Name,
|
|
||||||
paramDto.Placeholder,
|
|
||||||
paramDto.Type,
|
|
||||||
paramDto.Required)
|
|
||||||
{
|
|
||||||
DefaultValue = paramDto.DefaultValue,
|
|
||||||
Description = paramDto.Description
|
|
||||||
};
|
|
||||||
|
|
||||||
await _reportParameterRepository.InsertAsync(parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await GetTemplateAsync(template.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ReportTemplateDto> UpdateTemplateAsync(Guid id, UpdateReportTemplateDto input)
|
|
||||||
{
|
|
||||||
// 1) Şablonu getir ve alanlarını güncelle
|
|
||||||
var template = await _reportTemplateRepository.GetAsync(id);
|
|
||||||
|
|
||||||
template.Name = input.Name;
|
|
||||||
template.Description = input.Description;
|
|
||||||
template.HtmlContent = input.HtmlContent;
|
|
||||||
template.CategoryId = input.CategoryId;
|
|
||||||
template.Tags = JsonSerializer.Serialize(input.Tags ?? []);
|
|
||||||
|
|
||||||
// Şablonu hemen persist et (audit alanları için de iyi olur)
|
|
||||||
await _reportTemplateRepository.UpdateAsync(template, autoSave: true);
|
|
||||||
|
|
||||||
// 2) Parametrelerde upsert + artıklarını sil
|
|
||||||
var existingParams = await _reportParameterRepository.GetListAsync(p => p.TemplateId == id);
|
|
||||||
var existingById = existingParams.ToDictionary(p => p.Id, p => p);
|
|
||||||
|
|
||||||
var inputParams = input.Parameters ?? new List<UpdateReportParameterDto>();
|
|
||||||
|
|
||||||
// Id'si olan/olmayan diye ayır
|
|
||||||
var withId = inputParams.Where(x => x.Id.HasValue).ToList();
|
|
||||||
var withoutId = inputParams.Where(x => !x.Id.HasValue).ToList();
|
|
||||||
|
|
||||||
// 2.a) Id'si olanları güncelle (varsa) ya da ekle (yoksa)
|
|
||||||
foreach (var dto in withId)
|
|
||||||
{
|
|
||||||
var pid = dto.Id!.Value;
|
|
||||||
|
|
||||||
if (existingById.TryGetValue(pid, out var entity))
|
|
||||||
{
|
|
||||||
// Güncelle
|
|
||||||
entity.Name = dto.Name;
|
|
||||||
entity.Placeholder = dto.Placeholder;
|
|
||||||
entity.Type = dto.Type;
|
|
||||||
entity.Required = dto.Required;
|
|
||||||
entity.DefaultValue = dto.DefaultValue;
|
|
||||||
entity.Description = dto.Description;
|
|
||||||
|
|
||||||
await _reportParameterRepository.UpdateAsync(entity);
|
|
||||||
existingById.Remove(pid); // kalanlar silinecek listesinde kalmasın
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// DB'de yoksa yeni ekle (istemci Id göndermiş olabilir)
|
|
||||||
var newParam = new ReportParameter(
|
|
||||||
pid,
|
|
||||||
template.Id,
|
|
||||||
dto.Name,
|
|
||||||
dto.Placeholder,
|
|
||||||
dto.Type,
|
|
||||||
dto.Required)
|
|
||||||
{
|
|
||||||
DefaultValue = dto.DefaultValue,
|
|
||||||
Description = dto.Description
|
|
||||||
};
|
|
||||||
|
|
||||||
await _reportParameterRepository.InsertAsync(newParam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.b) Id'siz gelenleri yeni olarak ekle
|
|
||||||
foreach (var dto in withoutId)
|
|
||||||
{
|
|
||||||
var newParam = new ReportParameter(
|
|
||||||
GuidGenerator.Create(),
|
|
||||||
template.Id,
|
|
||||||
dto.Name,
|
|
||||||
dto.Placeholder,
|
|
||||||
dto.Type,
|
|
||||||
dto.Required)
|
|
||||||
{
|
|
||||||
DefaultValue = dto.DefaultValue,
|
|
||||||
Description = dto.Description
|
|
||||||
};
|
|
||||||
|
|
||||||
await _reportParameterRepository.InsertAsync(newParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.c) Input'ta olmayan eski parametreleri sil
|
|
||||||
foreach (var leftover in existingById.Values)
|
|
||||||
{
|
|
||||||
await _reportParameterRepository.DeleteAsync(leftover);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) Değişiklikleri tek seferde kaydet
|
|
||||||
await CurrentUnitOfWork.SaveChangesAsync();
|
|
||||||
|
|
||||||
// 4) Güncel DTO'yu dön
|
|
||||||
return await GetTemplateAsync(template.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public async Task DeleteTemplateAsync(Guid id)
|
|
||||||
{
|
|
||||||
await _reportTemplateRepository.DeleteAsync(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PagedResultDto<ReportGeneratedDto>> GetGeneratedReportsAsync(GetGeneratedReportsInput input)
|
|
||||||
{
|
|
||||||
var query = await _generatedReportRepository.GetQueryableAsync();
|
|
||||||
|
|
||||||
// Okuma senaryosu: tracking gerekmiyor + Template'ı eager load edelim
|
|
||||||
query = query.AsNoTracking()
|
|
||||||
.Include(x => x.ReportTemplate);
|
|
||||||
|
|
||||||
// Filtre
|
|
||||||
if (!string.IsNullOrWhiteSpace(input.Filter))
|
|
||||||
{
|
|
||||||
query = query.Where(x =>
|
|
||||||
x.TemplateName.Contains(input.Filter) ||
|
|
||||||
x.GeneratedContent.Contains(input.Filter)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.TemplateId.HasValue)
|
|
||||||
{
|
|
||||||
query = query.Where(x => x.TemplateId == input.TemplateId.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toplam kayıt
|
|
||||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
|
||||||
|
|
||||||
// Sıralama
|
|
||||||
if (!string.IsNullOrWhiteSpace(input.Sorting))
|
|
||||||
query = query.OrderBy(input.Sorting); // ör. "generatedAt DESC" veya "templateName"
|
|
||||||
else
|
|
||||||
query = query.OrderByDescending(x => x.CreationTime);
|
|
||||||
|
|
||||||
// Sayfalama
|
|
||||||
var reports = await AsyncExecuter.ToListAsync(
|
|
||||||
query.Skip(input.SkipCount).Take(input.MaxResultCount)
|
|
||||||
);
|
|
||||||
|
|
||||||
// DTO map
|
|
||||||
var reportDtos = reports.Select(MapToGeneratedReportDto).ToList();
|
|
||||||
|
|
||||||
return new PagedResultDto<ReportGeneratedDto>(totalCount, reportDtos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ReportGeneratedDto> GetGeneratedReportAsync(Guid id)
|
|
||||||
{
|
|
||||||
var report = await _generatedReportRepository.GetAsync(id);
|
|
||||||
|
|
||||||
return MapToGeneratedReportDto(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ReportGeneratedDto> GenerateReportAsync(ReportGenerateDto input)
|
|
||||||
{
|
|
||||||
var template = await _reportTemplateRepository.GetAsync(input.TemplateId);
|
|
||||||
if (template == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Template not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTML içeriğindeki parametreleri değiştir
|
|
||||||
var generatedContent = template.HtmlContent;
|
|
||||||
foreach (var param in input.Parameters)
|
|
||||||
{
|
|
||||||
var pattern = $"@@{param.Key}";
|
|
||||||
generatedContent = generatedContent.Replace(pattern, param.Value ?? "");
|
|
||||||
}
|
|
||||||
|
|
||||||
var generatedReport = new ReportGenerated(
|
|
||||||
GuidGenerator.Create(),
|
|
||||||
template.Id,
|
|
||||||
template.Name,
|
|
||||||
generatedContent,
|
|
||||||
JsonSerializer.Serialize(input.Parameters));
|
|
||||||
|
|
||||||
generatedReport = await _generatedReportRepository.InsertAsync(generatedReport, true);
|
|
||||||
|
|
||||||
return await GetGeneratedReportAsync(generatedReport.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteGeneratedReportAsync(Guid id)
|
|
||||||
{
|
|
||||||
await _generatedReportRepository.DeleteAsync(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ReportsDataDto> GetAllDataAsync()
|
|
||||||
{
|
|
||||||
var templatesInput = new GetReportTemplatesInput { MaxResultCount = 1000 };
|
|
||||||
var reportsInput = new GetGeneratedReportsInput { MaxResultCount = 1000 };
|
|
||||||
|
|
||||||
var templates = await GetTemplatesAsync(templatesInput);
|
|
||||||
var reports = await GetGeneratedReportsAsync(reportsInput);
|
|
||||||
|
|
||||||
return new ReportsDataDto
|
|
||||||
{
|
|
||||||
Templates = templates,
|
|
||||||
GeneratedReports = reports
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReportTemplateDto MapToReportTemplateDto(ReportTemplate template)
|
|
||||||
{
|
|
||||||
var dto = new ReportTemplateDto
|
|
||||||
{
|
|
||||||
Id = template.Id,
|
|
||||||
Name = template.Name,
|
|
||||||
Description = template.Description,
|
|
||||||
HtmlContent = template.HtmlContent,
|
|
||||||
CategoryId = template.CategoryId,
|
|
||||||
CreationTime = template.CreationTime,
|
|
||||||
LastModificationTime = template.LastModificationTime,
|
|
||||||
CreatorId = template.CreatorId,
|
|
||||||
LastModifierId = template.LastModifierId
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tags deserialize
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dto.Tags = string.IsNullOrEmpty(template.Tags)
|
|
||||||
? []
|
|
||||||
: JsonSerializer.Deserialize<List<string>>(template.Tags);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
dto.Tags = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parameters map
|
|
||||||
dto.Parameters = template.Parameters?.Select(p => new ReportParameterDto
|
|
||||||
{
|
|
||||||
Id = p.Id,
|
|
||||||
TemplateId = p.TemplateId,
|
|
||||||
Name = p.Name,
|
|
||||||
Placeholder = p.Placeholder,
|
|
||||||
Type = p.Type,
|
|
||||||
DefaultValue = p.DefaultValue,
|
|
||||||
Required = p.Required,
|
|
||||||
Description = p.Description
|
|
||||||
}).ToList() ?? [];
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReportGeneratedDto MapToGeneratedReportDto(ReportGenerated report)
|
|
||||||
{
|
|
||||||
var dto = new ReportGeneratedDto
|
|
||||||
{
|
|
||||||
Id = report.Id,
|
|
||||||
TemplateId = report.TemplateId,
|
|
||||||
TemplateName = report.TemplateName,
|
|
||||||
GeneratedContent = report.GeneratedContent,
|
|
||||||
CreationTime = report.CreationTime,
|
|
||||||
LastModificationTime = report.LastModificationTime,
|
|
||||||
CreatorId = report.CreatorId,
|
|
||||||
LastModifierId = report.LastModifierId
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parameters deserialize
|
|
||||||
try
|
|
||||||
{
|
|
||||||
dto.Parameters = string.IsNullOrEmpty(report.Parameters)
|
|
||||||
? new Dictionary<string, string>()
|
|
||||||
: JsonSerializer.Deserialize<Dictionary<string, string>>(report.Parameters);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
dto.Parameters = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template mapping
|
|
||||||
if (report.ReportTemplate != null)
|
|
||||||
{
|
|
||||||
dto.ReportTemplate = MapToReportTemplateDto(report.ReportTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,91 +0,0 @@
|
||||||
using AutoMapper;
|
|
||||||
using Erp.Platform.Entities;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Reports
|
|
||||||
{
|
|
||||||
public class ReportAutoMapperProfile : Profile
|
|
||||||
{
|
|
||||||
public ReportAutoMapperProfile()
|
|
||||||
{
|
|
||||||
CreateMap<ReportTemplate, ReportTemplateDto>()
|
|
||||||
.ForMember(dest => dest.Tags, opt => opt.MapFrom(src =>
|
|
||||||
ConvertTagsFromJson(src.Tags)))
|
|
||||||
.ForMember(dest => dest.Parameters, opt => opt.MapFrom(src => src.Parameters));
|
|
||||||
|
|
||||||
CreateMap<CreateReportTemplateDto, ReportTemplate>()
|
|
||||||
.ForMember(dest => dest.Tags, opt => opt.MapFrom(src => ConvertTagsToJson(src.Tags)))
|
|
||||||
.ForMember(dest => dest.Parameters, opt => opt.Ignore());
|
|
||||||
|
|
||||||
CreateMap<UpdateReportTemplateDto, ReportTemplate>()
|
|
||||||
.ForMember(dest => dest.Tags, opt => opt.MapFrom(src => ConvertTagsToJson(src.Tags)))
|
|
||||||
.ForMember(dest => dest.Parameters, opt => opt.Ignore());
|
|
||||||
|
|
||||||
CreateMap<ReportParameter, ReportParameterDto>();
|
|
||||||
|
|
||||||
CreateMap<CreateReportParameterDto, ReportParameter>()
|
|
||||||
.ForMember(dest => dest.Id, opt => opt.Ignore())
|
|
||||||
.ForMember(dest => dest.TemplateId, opt => opt.Ignore());
|
|
||||||
|
|
||||||
CreateMap<UpdateReportParameterDto, ReportParameter>()
|
|
||||||
.ForMember(dest => dest.TemplateId, opt => opt.Ignore());
|
|
||||||
|
|
||||||
CreateMap<ReportGenerated, ReportGeneratedDto>()
|
|
||||||
.ForMember(dest => dest.Parameters, opt => opt.MapFrom(src =>
|
|
||||||
ConvertParametersFromJson(src.Parameters)))
|
|
||||||
.ForMember(dest => dest.ReportTemplate, opt => opt.MapFrom(src => src.ReportTemplate));
|
|
||||||
|
|
||||||
CreateMap<ReportGenerateDto, ReportGenerated>()
|
|
||||||
.ForMember(dest => dest.Parameters, opt => opt.MapFrom(src => ConvertParametersToJson(src.Parameters)))
|
|
||||||
.ForMember(dest => dest.Id, opt => opt.Ignore())
|
|
||||||
.ForMember(dest => dest.TemplateId, opt => opt.MapFrom(src => src.TemplateId))
|
|
||||||
.ForMember(dest => dest.TemplateName, opt => opt.Ignore())
|
|
||||||
.ForMember(dest => dest.GeneratedContent, opt => opt.Ignore());
|
|
||||||
|
|
||||||
|
|
||||||
CreateMap<ReportCategory, ReportCategoryDto>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<string> ConvertTagsFromJson(string tags)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(tags))
|
|
||||||
return new List<string>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize<List<string>>(tags) ?? new List<string>();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return new List<string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ConvertTagsToJson(List<string> tags)
|
|
||||||
{
|
|
||||||
return JsonSerializer.Serialize(tags ?? new List<string>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Dictionary<string, string> ConvertParametersFromJson(string parameters)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(parameters))
|
|
||||||
return new Dictionary<string, string>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return JsonSerializer.Deserialize<Dictionary<string, string>>(parameters) ?? new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ConvertParametersToJson(Dictionary<string, string> parameters)
|
|
||||||
{
|
|
||||||
return JsonSerializer.Serialize(parameters ?? new Dictionary<string, string>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1335,315 +1335,9 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
"key": "App.Reports.Dashboard.All",
|
"key": "App.Reports.ReportTemplates",
|
||||||
"en": "All",
|
"en": "Report Templates",
|
||||||
"tr": "Tümü"
|
"tr": "Rapor Şablonları"
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.AllDescription",
|
|
||||||
"en": "Reports from all categories",
|
|
||||||
"tr": "Tüm kategorilere ait raporlar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.SearchTemplate",
|
|
||||||
"en": "Search template...",
|
|
||||||
"tr": "Şablon ara..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.NewTemplate",
|
|
||||||
"en": "New Template",
|
|
||||||
"tr": "Yeni Şablon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.TotalTemplates",
|
|
||||||
"en": "Total Templates",
|
|
||||||
"tr": "Toplam Şablon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.CategoryTemplates",
|
|
||||||
"en": "Category Templates",
|
|
||||||
"tr": "Kategori Şablonları"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.ActiveCategories",
|
|
||||||
"en": "Active Categories",
|
|
||||||
"tr": "Aktif Kategoriler"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.TotalParameters",
|
|
||||||
"en": "Total Parameters",
|
|
||||||
"tr": "Toplam Parametre"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.CategoryParameters",
|
|
||||||
"en": "Category Parameters",
|
|
||||||
"tr": "Kategori Parametreleri"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.NoTemplates",
|
|
||||||
"en": "No templates created yet",
|
|
||||||
"tr": "Henüz şablon oluşturulmamış"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.TemplateNotFound",
|
|
||||||
"en": "No template found",
|
|
||||||
"tr": "Şablon bulunamadı"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.CreateFirstTemplate",
|
|
||||||
"en": "Start by creating your first report template.",
|
|
||||||
"tr": "İlk rapor şablonunuzu oluşturarak başlayın."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.NoSearchResults",
|
|
||||||
"en": "No templates match your search criteria.",
|
|
||||||
"tr": "Arama kriterlerinize uygun şablon bulunamadı."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.Dashboard.DeleteTemplateConfirmation",
|
|
||||||
"en": "Are you sure you want to delete this template?",
|
|
||||||
"tr": "Bu şablonu silmek istediğinizden emin misiniz?"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportGenerator.ReportParameters",
|
|
||||||
"en": "Report Parameters",
|
|
||||||
"tr": "Rapor Parametreleri"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportGenerator.ParameterValues",
|
|
||||||
"en": "Parameter Values",
|
|
||||||
"tr": "Parametre Değerleri"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportGenerator.RequiredFieldsNote",
|
|
||||||
"en": "* Required fields",
|
|
||||||
"tr": "* Zorunlu alanlar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportGenerator.NoParameters",
|
|
||||||
"en": "No parameters defined for this template.",
|
|
||||||
"tr": "Bu şablon için parametre tanımlanmamış."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportGenerator.DirectGenerate",
|
|
||||||
"en": "You can directly generate the report.",
|
|
||||||
"tr": "Direkt rapor oluşturabilirsiniz."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportGenerator.GenerateReport",
|
|
||||||
"en": "Generate Report",
|
|
||||||
"tr": "Rapor Oluştur"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportHtmlViewer.Placeholder",
|
|
||||||
"en": "Write your report template here...",
|
|
||||||
"tr": "Rapor şablonunuzu buraya yazın..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.LoadingTitle",
|
|
||||||
"en": "Loading report...",
|
|
||||||
"tr": "Rapor yükleniyor..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.LoadingSubtitle",
|
|
||||||
"en": "Please wait",
|
|
||||||
"tr": "Lütfen bekleyin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.ErrorNotFound",
|
|
||||||
"en": "Report not found",
|
|
||||||
"tr": "Rapor bulunamadı"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.ErrorNotFoundDescription",
|
|
||||||
"en": "The report you are looking for may not exist or has been deleted.",
|
|
||||||
"tr": "Aradığınız rapor mevcut değil veya silinmiş olabilir."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.DownloadPDF",
|
|
||||||
"en": "Download Pdf",
|
|
||||||
"tr": "Pdf İndir"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.Print",
|
|
||||||
"en": "Print",
|
|
||||||
"tr": "Yazdır"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.Page",
|
|
||||||
"en": "Page",
|
|
||||||
"tr": "Sayfa"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateCard.Show",
|
|
||||||
"en": "Show",
|
|
||||||
"tr": "Göster"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.TitleEdit",
|
|
||||||
"en": "Edit Template",
|
|
||||||
"tr": "Şablon Düzenle"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.TitleNew",
|
|
||||||
"en": "Create New Template",
|
|
||||||
"tr": "Yeni Şablon Oluştur"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Tab.Info",
|
|
||||||
"en": "Template Info",
|
|
||||||
"tr": "Şablon Bilgileri"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Tab.Parameters",
|
|
||||||
"en": "Parameters",
|
|
||||||
"tr": "Parametreler"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Tab.Content",
|
|
||||||
"en": "HTML Content",
|
|
||||||
"tr": "HTML İçerik"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Label.Name",
|
|
||||||
"en": "Template Name",
|
|
||||||
"tr": "Şablon Adı"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Placeholder.Name",
|
|
||||||
"en": "Report template name",
|
|
||||||
"tr": "Rapor şablonu adı"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Label.Category",
|
|
||||||
"en": "Category",
|
|
||||||
"tr": "Kategori"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Placeholder.SelectCategory",
|
|
||||||
"en": "Select Category",
|
|
||||||
"tr": "Kategori Seç"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Label.Tags",
|
|
||||||
"en": "Tags",
|
|
||||||
"tr": "Etiketler"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Placeholder.AddTag",
|
|
||||||
"en": "Add tag...",
|
|
||||||
"tr": "Etiket ekle..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Button.Add",
|
|
||||||
"en": "Add",
|
|
||||||
"tr": "Ekle"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Label.Description",
|
|
||||||
"en": "Template Description",
|
|
||||||
"tr": "Şablon Açıklaması"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Placeholder.Description",
|
|
||||||
"en": "Write detailed description about the template...",
|
|
||||||
"tr": "Şablon hakkında detaylı açıklama yazın..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.NoParameters",
|
|
||||||
"en": "No parameters detected yet",
|
|
||||||
"tr": "Henüz parametre algılanmadı"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.NoParametersDescription",
|
|
||||||
"en": "When you use parameters in the format @@PARAMETER in HTML content, they will appear here.",
|
|
||||||
"tr": "HTML içeriğinde @@PARAMETRE formatında parametreler kullandığınızda burada görünecek."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Placeholder.ParameterDescription",
|
|
||||||
"en": "Parameter description",
|
|
||||||
"tr": "Parametre açıklaması"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Button.Saving",
|
|
||||||
"en": "Saving...",
|
|
||||||
"tr": "Kaydediliyor..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.TemplateEditor.Button.Save",
|
|
||||||
"en": "Save",
|
|
||||||
"tr": "Kaydet"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.ReportIdMissing",
|
|
||||||
"en": "Report not found",
|
|
||||||
"tr": "Rapor bulunamadı"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.ReportLoadError",
|
|
||||||
"en": "An error occurred while loading the report",
|
|
||||||
"tr": "Rapor yüklenirken bir hata oluştu"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.ZoomIn",
|
|
||||||
"en": "Zoom In",
|
|
||||||
"tr": "Yakınlaştır"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"resourceName": "Platform",
|
|
||||||
"key": "App.Reports.ReportViewer.ZoomOut",
|
|
||||||
"en": "Zoom Out",
|
|
||||||
"tr": "Uzaklaştır"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"resourceName": "Platform",
|
"resourceName": "Platform",
|
||||||
|
|
|
||||||
|
|
@ -5938,6 +5938,196 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region ReportTemplates
|
||||||
|
listFormName = AppCodes.Reports.ReportTemplates;
|
||||||
|
if (!await _listFormRepository.AnyAsync(a => a.ListFormCode == listFormName))
|
||||||
|
{
|
||||||
|
var listForm = await _listFormRepository.InsertAsync(
|
||||||
|
new ListForm()
|
||||||
|
{
|
||||||
|
ListFormType = ListFormTypeEnum.List,
|
||||||
|
ExportJson = DefaultExportJson,
|
||||||
|
IsSubForm = false,
|
||||||
|
ShowNote = true,
|
||||||
|
LayoutJson = DefaultLayoutJson(),
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
ListFormCode = listFormName,
|
||||||
|
Name = listFormName,
|
||||||
|
Title = listFormName,
|
||||||
|
DataSourceCode = SeedConsts.DataSources.DefaultCode,
|
||||||
|
IsTenant = true,
|
||||||
|
IsBranch = false,
|
||||||
|
IsOrganizationUnit = false,
|
||||||
|
Description = listFormName,
|
||||||
|
SelectCommandType = SelectCommandTypeEnum.Table,
|
||||||
|
SelectCommand = TableNameResolver.GetFullTableName(nameof(TableNameEnum.ReportTemplate)),
|
||||||
|
KeyFieldName = "Id",
|
||||||
|
KeyFieldDbSourceType = DbType.Guid,
|
||||||
|
DefaultFilter = DefaultFilterJson,
|
||||||
|
SortMode = GridOptions.SortModeSingle,
|
||||||
|
FilterRowJson = DefaultFilterRowJson,
|
||||||
|
HeaderFilterJson = DefaultHeaderFilterJson,
|
||||||
|
SearchPanelJson = DefaultSearchPanelJson,
|
||||||
|
GroupPanelJson = DefaultGroupPanelJson,
|
||||||
|
SelectionJson = DefaultSelectionSingleJson,
|
||||||
|
ColumnOptionJson = DefaultColumnOptionJson,
|
||||||
|
PermissionJson = DefaultPermissionJson(listFormName),
|
||||||
|
DeleteCommand = DefaultDeleteCommand(nameof(TableNameEnum.ReportTemplate)),
|
||||||
|
DeleteFieldsDefaultValueJson = DefaultDeleteFieldsDefaultValueJson(),
|
||||||
|
PagerOptionJson = DefaultPagerOptionJson,
|
||||||
|
EditingOptionJson = DefaultEditingOptionJson(listFormName, 900, 500, true, true, true, true, false),
|
||||||
|
EditingFormJson = JsonSerializer.Serialize(new List<EditingFormDto>()
|
||||||
|
{
|
||||||
|
new() {
|
||||||
|
Order = 1, ColCount = 1, ColSpan = 1, ItemType = "group", Items =
|
||||||
|
[
|
||||||
|
new EditingFormItemDto { Order = 1, DataField = "Name", ColSpan = 1, IsRequired = true, EditorType2 = EditorTypes.dxTextBox },
|
||||||
|
new EditingFormItemDto { Order = 2, DataField = "Description", ColSpan = 1, EditorType2 = EditorTypes.dxTextArea },
|
||||||
|
new EditingFormItemDto { Order = 3, DataField = "CategoryId", ColSpan = 1, EditorType2 = EditorTypes.dxSelectBox },
|
||||||
|
new EditingFormItemDto { Order = 4, DataField = "HtmlContent", ColSpan = 1, EditorType2 = EditorTypes.dxHtmlEditor, EditorOptions = EditorOptionValues.HtmlEditorOptions },
|
||||||
|
new EditingFormItemDto { Order = 5, DataField = "Status", ColSpan = 1, EditorType2 = EditorTypes.dxSelectBox },
|
||||||
|
]}
|
||||||
|
}),
|
||||||
|
InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson(),
|
||||||
|
FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] {
|
||||||
|
new() { FieldName = "Status", FieldDbType = DbType.String, Value = "Aktif", CustomValueType = FieldCustomValueTypeEnum.Value },
|
||||||
|
}),
|
||||||
|
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
|
||||||
|
new() {
|
||||||
|
Hint = "View",
|
||||||
|
Text ="View",
|
||||||
|
UrlTarget="_blank",
|
||||||
|
AuthName = listFormName,
|
||||||
|
Url=$"/admin/reports/@Id/view",
|
||||||
|
IsVisible = true,
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
Hint = "Design",
|
||||||
|
Text ="Design",
|
||||||
|
UrlTarget="_blank",
|
||||||
|
AuthName = listFormName + ".Update",
|
||||||
|
Url=$"/admin/reports/@Id/design",
|
||||||
|
IsVisible = true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#region HtmlReports Fields
|
||||||
|
await _listFormFieldRepository.InsertManyAsync(
|
||||||
|
[
|
||||||
|
// Id
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Guid,
|
||||||
|
FieldName = "Id",
|
||||||
|
Width = 100,
|
||||||
|
ListOrderNo = 1,
|
||||||
|
Visible = false,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
// String alanlar
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Name",
|
||||||
|
Width = 250,
|
||||||
|
ListOrderNo = 2,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
SortIndex = 1,
|
||||||
|
SortDirection = GridColumnOptions.SortOrderAsc,
|
||||||
|
AllowSearch = true,
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.Guid,
|
||||||
|
FieldName = "CategoryId",
|
||||||
|
Width = 300,
|
||||||
|
ListOrderNo = 3,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
LookupJson = LookupQueryValues.DefaultLookupQueryJson(nameof(TableNameEnum.ReportCategory), "Id", "Name"),
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto{ C = AppCodes.Definitions.Lawyer + ".Create", R = AppCodes.Definitions.Lawyer, U = AppCodes.Definitions.Lawyer + ".Update", E = true, I = true, Deny = false }),
|
||||||
|
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto{ IsPivot = true })
|
||||||
|
},
|
||||||
|
new() {
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Status",
|
||||||
|
Width = 100,
|
||||||
|
ListOrderNo = 4,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
LookupJson = JsonSerializer.Serialize(new LookupDto {
|
||||||
|
DataSourceType = UiLookupDataSourceTypeEnum.StaticData,
|
||||||
|
DisplayExpr = "name",
|
||||||
|
ValueExpr = "key",
|
||||||
|
LookupQuery = JsonSerializer.Serialize(new LookupDataDto[] {
|
||||||
|
new () { Key="Aktif", Name="Aktif" },
|
||||||
|
new () { Key="Pasif", Name="Pasif" },
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
ValidationRuleJson = DefaultValidationRuleRequiredJson,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto{ C = AppCodes.Definitions.Lawyer + ".Create", R = AppCodes.Definitions.Lawyer, U = AppCodes.Definitions.Lawyer + ".Update", E = true, I = true, Deny = false }),
|
||||||
|
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto{ IsPivot = true })
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "Description",
|
||||||
|
Width = 250,
|
||||||
|
ListOrderNo = 5,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
ListFormCode = listForm.ListFormCode,
|
||||||
|
CultureName = LanguageCodes.En,
|
||||||
|
SourceDbType = DbType.String,
|
||||||
|
FieldName = "HtmlContent",
|
||||||
|
Width = 250,
|
||||||
|
ListOrderNo = 6,
|
||||||
|
Visible = true,
|
||||||
|
IsActive = true,
|
||||||
|
IsDeleted = false,
|
||||||
|
ColumnCustomizationJson = DefaultColumnCustomizationJson,
|
||||||
|
PermissionJson = DefaultFieldPermissionJson(listForm.Name),
|
||||||
|
PivotSettingsJson = DefaultPivotSettingsJson
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -364,20 +364,6 @@
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": ["App.DeveloperKit.Components"]
|
"authority": ["App.DeveloperKit.Components"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"key": "admin.reportManagement",
|
|
||||||
"path": "/admin/reports/management",
|
|
||||||
"componentPath": "@/views/report/DashboardPage",
|
|
||||||
"routeType": "protected",
|
|
||||||
"authority": ["App.Reports.Management"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "admin.reports.view",
|
|
||||||
"path": "/admin/reports/:id",
|
|
||||||
"componentPath": "@/views/report/ReportViewerPage",
|
|
||||||
"routeType": "protected",
|
|
||||||
"authority": ["App.Reports.Categories"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "admin.fileManagement",
|
"key": "admin.fileManagement",
|
||||||
"path": "/admin/files",
|
"path": "/admin/files",
|
||||||
|
|
@ -457,14 +443,14 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "admin.devexpressReportView",
|
"key": "admin.devexpressReportView",
|
||||||
"path": "/admin/reports/reportviewer/:id",
|
"path": "/admin/reports/:id/view",
|
||||||
"componentPath": "@/views/report/DevexpressReportViewer",
|
"componentPath": "@/views/report/DevexpressReportViewer",
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": []
|
"authority": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "admin.devexpressReportDesigner",
|
"key": "admin.devexpressReportDesigner",
|
||||||
"path": "/admin/reports/reportdesigner/:id",
|
"path": "/admin/reports/:id/design",
|
||||||
"componentPath": "@/views/report/DevexpressReportDesigner",
|
"componentPath": "@/views/report/DevexpressReportDesigner",
|
||||||
"routeType": "protected",
|
"routeType": "protected",
|
||||||
"authority": []
|
"authority": []
|
||||||
|
|
@ -1024,151 +1010,21 @@
|
||||||
"RequiredPermissionName": "App.AuditLogs",
|
"RequiredPermissionName": "App.AuditLogs",
|
||||||
"IsDisabled": false
|
"IsDisabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ParentCode": "App.Administration",
|
|
||||||
"Code": "App.Files",
|
|
||||||
"DisplayName": "App.Files",
|
|
||||||
"Order": 4,
|
|
||||||
"Url": "/admin/files",
|
|
||||||
"Icon": "FcFolder",
|
|
||||||
"RequiredPermissionName": "App.Files",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Forum",
|
"Code": "App.Forum",
|
||||||
"DisplayName": "App.Forum",
|
"DisplayName": "App.Forum",
|
||||||
"Order": 5,
|
"Order": 4,
|
||||||
"Url": "/admin/forum",
|
"Url": "/admin/forum",
|
||||||
"Icon": "FcLink",
|
"Icon": "FcLink",
|
||||||
"RequiredPermissionName": "App.ForumManagement.Publish",
|
"RequiredPermissionName": "App.ForumManagement.Publish",
|
||||||
"IsDisabled": false
|
"IsDisabled": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ParentCode": "App.Administration",
|
|
||||||
"Code": "App.Reports.Management",
|
|
||||||
"DisplayName": "App.Reports.Management",
|
|
||||||
"Order": 6,
|
|
||||||
"Url": null,
|
|
||||||
"Icon": "FcDocument",
|
|
||||||
"RequiredPermissionName": null,
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.Reports.Management",
|
|
||||||
"Code": "App.Reports.Categories",
|
|
||||||
"DisplayName": "App.Reports.Categories",
|
|
||||||
"Order": 1,
|
|
||||||
"Url": "/admin/list/App.Reports.Categories",
|
|
||||||
"Icon": "FcProcess",
|
|
||||||
"RequiredPermissionName": "App.Reports.Categories",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.Reports.Management",
|
|
||||||
"Code": "App.Reports",
|
|
||||||
"DisplayName": "App.Reports",
|
|
||||||
"Order": 2,
|
|
||||||
"Url": "/admin/reports/management",
|
|
||||||
"Icon": "FcSimCardChip",
|
|
||||||
"RequiredPermissionName": "App.Reports.Management",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.Administration",
|
|
||||||
"Code": "App.DeveloperKit",
|
|
||||||
"DisplayName": "App.DeveloperKit",
|
|
||||||
"Order": 8,
|
|
||||||
"Url": null,
|
|
||||||
"Icon": "FcAndroidOs",
|
|
||||||
"RequiredPermissionName": null,
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.DeveloperKit",
|
|
||||||
"Code": "App.DeveloperKit.Dashboard",
|
|
||||||
"DisplayName": "App.Coordinator.Classroom.Dashboard",
|
|
||||||
"Order": 1,
|
|
||||||
"Url": "/admin/developerkit",
|
|
||||||
"Icon": "FcBinoculars",
|
|
||||||
"RequiredPermissionName": "App.DeveloperKit",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.DeveloperKit",
|
|
||||||
"Code": "App.DeveloperKit.Entity",
|
|
||||||
"DisplayName": "App.DeveloperKit.Entity",
|
|
||||||
"Order": 2,
|
|
||||||
"Url": "/admin/developerkit/entities",
|
|
||||||
"Icon": "FcAddRow",
|
|
||||||
"RequiredPermissionName": "App.DeveloperKit.Entity",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.DeveloperKit",
|
|
||||||
"Code": "App.DeveloperKit.Migrations",
|
|
||||||
"DisplayName": "App.DeveloperKit.Migrations",
|
|
||||||
"Order": 3,
|
|
||||||
"Url": "/admin/developerkit/migrations",
|
|
||||||
"Icon": "FcAddDatabase",
|
|
||||||
"RequiredPermissionName": "App.DeveloperKit.Migrations",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.DeveloperKit",
|
|
||||||
"Code": "App.DeveloperKit.CrudEndpoints",
|
|
||||||
"DisplayName": "App.DeveloperKit.CrudEndpoints",
|
|
||||||
"Order": 4,
|
|
||||||
"Url": "/admin/developerkit/endpoints",
|
|
||||||
"Icon": "FcOrgUnit",
|
|
||||||
"RequiredPermissionName": "App.DeveloperKit.CrudEndpoints",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.DeveloperKit",
|
|
||||||
"Code": "App.DeveloperKit.CustomEndpoints",
|
|
||||||
"DisplayName": "App.DeveloperKit.CustomEndpoints",
|
|
||||||
"Order": 5,
|
|
||||||
"Url": "/admin/list/App.DeveloperKit.CustomEndpoints",
|
|
||||||
"Icon": "FcMindMap",
|
|
||||||
"RequiredPermissionName": "App.DeveloperKit.CustomEndpoints",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ParentCode": "App.DeveloperKit",
|
|
||||||
"Code": "App.DeveloperKit.Components",
|
|
||||||
"DisplayName": "App.DeveloperKit.Components",
|
|
||||||
"Order": 6,
|
|
||||||
"Url": "/admin/developerkit/components",
|
|
||||||
"Icon": "FcBiohazard",
|
|
||||||
"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.SqlQueryManager",
|
|
||||||
"DisplayName": "App.SqlQueryManager",
|
|
||||||
"Order": 9,
|
|
||||||
"Url": "/admin/sqlQueryManager",
|
|
||||||
"Icon": "FaDatabase",
|
|
||||||
"RequiredPermissionName": "App.SqlQueryManager",
|
|
||||||
"IsDisabled": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Intranet",
|
"Code": "App.Intranet",
|
||||||
"DisplayName": "App.Intranet",
|
"DisplayName": "App.Intranet",
|
||||||
"Order": 7,
|
"Order": 5,
|
||||||
"Url": null,
|
"Url": null,
|
||||||
"Icon": "FcDataConfiguration",
|
"Icon": "FcDataConfiguration",
|
||||||
"RequiredPermissionName": null,
|
"RequiredPermissionName": null,
|
||||||
|
|
@ -1268,7 +1124,7 @@
|
||||||
"ParentCode": "App.Administration",
|
"ParentCode": "App.Administration",
|
||||||
"Code": "App.Public",
|
"Code": "App.Public",
|
||||||
"DisplayName": "App.Public",
|
"DisplayName": "App.Public",
|
||||||
"Order": 8,
|
"Order": 6,
|
||||||
"Url": null,
|
"Url": null,
|
||||||
"Icon": "FcGenealogy",
|
"Icon": "FcGenealogy",
|
||||||
"RequiredPermissionName": null,
|
"RequiredPermissionName": null,
|
||||||
|
|
@ -1374,6 +1230,136 @@
|
||||||
"RequiredPermissionName": "App.Contact",
|
"RequiredPermissionName": "App.Contact",
|
||||||
"IsDisabled": false
|
"IsDisabled": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Administration",
|
||||||
|
"Code": "App.Files",
|
||||||
|
"DisplayName": "App.Files",
|
||||||
|
"Order": 7,
|
||||||
|
"Url": "/admin/files",
|
||||||
|
"Icon": "FcFolder",
|
||||||
|
"RequiredPermissionName": "App.Files",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Administration",
|
||||||
|
"Code": "App.Reports.Management",
|
||||||
|
"DisplayName": "App.Reports.Management",
|
||||||
|
"Order": 8,
|
||||||
|
"Url": null,
|
||||||
|
"Icon": "FcDocument",
|
||||||
|
"RequiredPermissionName": null,
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Reports.Management",
|
||||||
|
"Code": "App.Reports.Categories",
|
||||||
|
"DisplayName": "App.Reports.Categories",
|
||||||
|
"Order": 1,
|
||||||
|
"Url": "/admin/list/App.Reports.Categories",
|
||||||
|
"Icon": "FcProcess",
|
||||||
|
"RequiredPermissionName": "App.Reports.Categories",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Reports.Management",
|
||||||
|
"Code": "App.Reports.ReportTemplates",
|
||||||
|
"DisplayName": "App.Reports.ReportTemplates",
|
||||||
|
"Order": 2,
|
||||||
|
"Url": "/admin/list/App.Reports.ReportTemplates",
|
||||||
|
"Icon": "FcSimCardChip",
|
||||||
|
"RequiredPermissionName": "App.Reports.ReportTemplates",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.Administration",
|
||||||
|
"Code": "App.DeveloperKit",
|
||||||
|
"DisplayName": "App.DeveloperKit",
|
||||||
|
"Order": 9,
|
||||||
|
"Url": null,
|
||||||
|
"Icon": "FcAndroidOs",
|
||||||
|
"RequiredPermissionName": null,
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.DeveloperKit",
|
||||||
|
"Code": "App.DeveloperKit.Dashboard",
|
||||||
|
"DisplayName": "App.Coordinator.Classroom.Dashboard",
|
||||||
|
"Order": 1,
|
||||||
|
"Url": "/admin/developerkit",
|
||||||
|
"Icon": "FcBinoculars",
|
||||||
|
"RequiredPermissionName": "App.DeveloperKit",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.DeveloperKit",
|
||||||
|
"Code": "App.DeveloperKit.Entity",
|
||||||
|
"DisplayName": "App.DeveloperKit.Entity",
|
||||||
|
"Order": 2,
|
||||||
|
"Url": "/admin/developerkit/entities",
|
||||||
|
"Icon": "FcAddRow",
|
||||||
|
"RequiredPermissionName": "App.DeveloperKit.Entity",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.DeveloperKit",
|
||||||
|
"Code": "App.DeveloperKit.Migrations",
|
||||||
|
"DisplayName": "App.DeveloperKit.Migrations",
|
||||||
|
"Order": 3,
|
||||||
|
"Url": "/admin/developerkit/migrations",
|
||||||
|
"Icon": "FcAddDatabase",
|
||||||
|
"RequiredPermissionName": "App.DeveloperKit.Migrations",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.DeveloperKit",
|
||||||
|
"Code": "App.DeveloperKit.CrudEndpoints",
|
||||||
|
"DisplayName": "App.DeveloperKit.CrudEndpoints",
|
||||||
|
"Order": 4,
|
||||||
|
"Url": "/admin/developerkit/endpoints",
|
||||||
|
"Icon": "FcOrgUnit",
|
||||||
|
"RequiredPermissionName": "App.DeveloperKit.CrudEndpoints",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.DeveloperKit",
|
||||||
|
"Code": "App.DeveloperKit.CustomEndpoints",
|
||||||
|
"DisplayName": "App.DeveloperKit.CustomEndpoints",
|
||||||
|
"Order": 5,
|
||||||
|
"Url": "/admin/list/App.DeveloperKit.CustomEndpoints",
|
||||||
|
"Icon": "FcMindMap",
|
||||||
|
"RequiredPermissionName": "App.DeveloperKit.CustomEndpoints",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ParentCode": "App.DeveloperKit",
|
||||||
|
"Code": "App.DeveloperKit.Components",
|
||||||
|
"DisplayName": "App.DeveloperKit.Components",
|
||||||
|
"Order": 6,
|
||||||
|
"Url": "/admin/developerkit/components",
|
||||||
|
"Icon": "FcBiohazard",
|
||||||
|
"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.SqlQueryManager",
|
||||||
|
"DisplayName": "App.SqlQueryManager",
|
||||||
|
"Order": 10,
|
||||||
|
"Url": "/admin/sqlQueryManager",
|
||||||
|
"Icon": "FaDatabase",
|
||||||
|
"RequiredPermissionName": "App.SqlQueryManager",
|
||||||
|
"IsDisabled": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ParentCode": null,
|
"ParentCode": null,
|
||||||
"Code": "App.Participant",
|
"Code": "App.Participant",
|
||||||
|
|
|
||||||
|
|
@ -2531,17 +2531,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management",
|
"Name": "App.Reports.ReportTemplates",
|
||||||
"ParentName": null,
|
"ParentName": null,
|
||||||
"DisplayName": "App.Reports.Management",
|
"DisplayName": "App.Reports.ReportTemplates",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
"MenuGroup": "Erp|Kurs"
|
"MenuGroup": "Erp|Kurs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management.Create",
|
"Name": "App.Reports.ReportTemplates.Create",
|
||||||
"ParentName": "App.Reports.Management",
|
"ParentName": "App.Reports.ReportTemplates",
|
||||||
"DisplayName": "Create",
|
"DisplayName": "Create",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -2549,8 +2549,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management.Delete",
|
"Name": "App.Reports.ReportTemplates.Delete",
|
||||||
"ParentName": "App.Reports.Management",
|
"ParentName": "App.Reports.ReportTemplates",
|
||||||
"DisplayName": "Delete",
|
"DisplayName": "Delete",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -2558,8 +2558,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management.Export",
|
"Name": "App.Reports.ReportTemplates.Export",
|
||||||
"ParentName": "App.Reports.Management",
|
"ParentName": "App.Reports.ReportTemplates",
|
||||||
"DisplayName": "Export",
|
"DisplayName": "Export",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -2567,8 +2567,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management.Import",
|
"Name": "App.Reports.ReportTemplates.Import",
|
||||||
"ParentName": "App.Reports.Management",
|
"ParentName": "App.Reports.ReportTemplates",
|
||||||
"DisplayName": "Import",
|
"DisplayName": "Import",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -2576,8 +2576,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management.Note",
|
"Name": "App.Reports.ReportTemplates.Note",
|
||||||
"ParentName": "App.Reports.Management",
|
"ParentName": "App.Reports.ReportTemplates",
|
||||||
"DisplayName": "Note",
|
"DisplayName": "Note",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
@ -2585,8 +2585,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"GroupName": "App.Administration",
|
"GroupName": "App.Administration",
|
||||||
"Name": "App.Reports.Management.Update",
|
"Name": "App.Reports.ReportTemplates.Update",
|
||||||
"ParentName": "App.Reports.Management",
|
"ParentName": "App.Reports.ReportTemplates",
|
||||||
"DisplayName": "Update",
|
"DisplayName": "Update",
|
||||||
"IsEnabled": true,
|
"IsEnabled": true,
|
||||||
"MultiTenancySide": 3,
|
"MultiTenancySide": 3,
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ public enum TableNameEnum
|
||||||
CustomComponent,
|
CustomComponent,
|
||||||
ReportCategory,
|
ReportCategory,
|
||||||
ReportTemplate,
|
ReportTemplate,
|
||||||
ReportParameter,
|
|
||||||
ReportGenerated,
|
|
||||||
IpRestriction,
|
IpRestriction,
|
||||||
Sector,
|
Sector,
|
||||||
ContactTag,
|
ContactTag,
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,6 @@ public static class TableNameResolver
|
||||||
{ nameof(TableNameEnum.DynamicService), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.DynamicService), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.ReportCategory), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.ReportCategory), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.ReportTemplate), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.ReportTemplate), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.ReportParameter), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
|
||||||
{ nameof(TableNameEnum.ReportGenerated), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
|
||||||
{ nameof(TableNameEnum.IpRestriction), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.IpRestriction), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||||
{ nameof(TableNameEnum.Sector), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
{ nameof(TableNameEnum.Sector), (TablePrefix.TenantByName, MenuPrefix.Saas) },
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -373,6 +373,7 @@ public static class SeedConsts
|
||||||
{
|
{
|
||||||
public const string Default = Prefix.App + ".Reports";
|
public const string Default = Prefix.App + ".Reports";
|
||||||
public const string Categories = Default + ".Categories";
|
public const string Categories = Default + ".Categories";
|
||||||
|
public const string ReportTemplates = Default + ".ReportTemplates";
|
||||||
}
|
}
|
||||||
//Web Site
|
//Web Site
|
||||||
public const string About = Prefix.App + ".About";
|
public const string About = Prefix.App + ".About";
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ namespace Erp.Platform.Entities
|
||||||
public string Icon { get; set; }
|
public string Icon { get; set; }
|
||||||
|
|
||||||
public ICollection<ReportTemplate> ReportTemplates { get; set; }
|
public ICollection<ReportTemplate> ReportTemplates { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
using System;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
|
||||||
using Volo.Abp.MultiTenancy;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Entities
|
|
||||||
{
|
|
||||||
public class ReportGenerated : FullAuditedEntity<Guid>, IMultiTenant
|
|
||||||
{
|
|
||||||
public Guid? TenantId { get; set; }
|
|
||||||
|
|
||||||
public Guid? TemplateId { get; set; }
|
|
||||||
public string TemplateName { get; set; }
|
|
||||||
public string GeneratedContent { get; set; }
|
|
||||||
public string Parameters { get; set; }
|
|
||||||
|
|
||||||
public virtual ReportTemplate ReportTemplate { get; set; }
|
|
||||||
|
|
||||||
public ReportGenerated()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportGenerated(
|
|
||||||
Guid id,
|
|
||||||
Guid templateId,
|
|
||||||
string templateName,
|
|
||||||
string generatedContent,
|
|
||||||
string parameters
|
|
||||||
) : base(id)
|
|
||||||
{
|
|
||||||
TemplateId = templateId;
|
|
||||||
TemplateName = templateName;
|
|
||||||
GeneratedContent = generatedContent;
|
|
||||||
Parameters = parameters;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
using System;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
|
||||||
using Volo.Abp.MultiTenancy;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Entities
|
|
||||||
{
|
|
||||||
public class ReportParameter : FullAuditedEntity<Guid>, IMultiTenant
|
|
||||||
{
|
|
||||||
public Guid? TenantId { get; set; }
|
|
||||||
|
|
||||||
public Guid? TemplateId { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Placeholder { get; set; }
|
|
||||||
public string Type { get; set; }
|
|
||||||
public string DefaultValue { get; set; }
|
|
||||||
public bool Required { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
public virtual ReportTemplate ReportTemplate { get; set; }
|
|
||||||
|
|
||||||
public ReportParameter()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportParameter(
|
|
||||||
Guid id,
|
|
||||||
Guid templateId,
|
|
||||||
string name,
|
|
||||||
string placeholder,
|
|
||||||
string type,
|
|
||||||
bool required = false
|
|
||||||
) : base(id)
|
|
||||||
{
|
|
||||||
TemplateId = templateId;
|
|
||||||
Name = name;
|
|
||||||
Placeholder = placeholder;
|
|
||||||
Type = type;
|
|
||||||
Required = required;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Volo.Abp.Domain.Entities.Auditing;
|
using Volo.Abp.Domain.Entities.Auditing;
|
||||||
using Volo.Abp.MultiTenancy;
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
||||||
|
|
@ -13,33 +12,24 @@ namespace Erp.Platform.Entities
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
public string HtmlContent { get; set; }
|
public string HtmlContent { get; set; }
|
||||||
public Guid CategoryId { get; set; }
|
public Guid CategoryId { get; set; }
|
||||||
public string Tags { get; set; }
|
public string Status { get; set; }
|
||||||
|
|
||||||
public ReportCategory ReportCategory { get; set; }
|
public ReportCategory ReportCategory { get; set; }
|
||||||
|
|
||||||
public ICollection<ReportParameter> Parameters { get; set; }
|
|
||||||
public ICollection<ReportGenerated> Generated { get; set; }
|
|
||||||
|
|
||||||
public ReportTemplate()
|
|
||||||
{
|
|
||||||
Parameters = [];
|
|
||||||
Generated = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReportTemplate(
|
public ReportTemplate(
|
||||||
Guid id,
|
Guid id,
|
||||||
string name,
|
string name,
|
||||||
string description,
|
string description,
|
||||||
string htmlContent,
|
string htmlContent,
|
||||||
Guid categoryId
|
Guid categoryId,
|
||||||
|
string status
|
||||||
) : base(id)
|
) : base(id)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Description = description;
|
Description = description;
|
||||||
HtmlContent = htmlContent;
|
HtmlContent = htmlContent;
|
||||||
CategoryId = categoryId;
|
CategoryId = categoryId;
|
||||||
Parameters = [];
|
Status = status;
|
||||||
Generated = [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Erp.Platform.Entities;
|
|
||||||
using Volo.Abp.Domain.Repositories;
|
|
||||||
|
|
||||||
namespace Erp.Platform.Repositories
|
|
||||||
{
|
|
||||||
public interface IGeneratedReportRepository : IRepository<ReportGenerated, Guid>
|
|
||||||
{
|
|
||||||
Task<List<ReportGenerated>> GetListAsync(
|
|
||||||
int skipCount = 0,
|
|
||||||
int maxResultCount = int.MaxValue,
|
|
||||||
string sorting = null,
|
|
||||||
string filter = null,
|
|
||||||
Guid? templateId = null
|
|
||||||
);
|
|
||||||
|
|
||||||
Task<long> GetCountAsync(string filter = null, Guid? templateId = null);
|
|
||||||
|
|
||||||
Task<List<ReportGenerated>> GetByTemplateIdAsync(Guid? templateId);
|
|
||||||
|
|
||||||
Task<ReportGenerated> GetByIdWithTemplateAsync(Guid id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -66,8 +66,6 @@ public class PlatformDbContext :
|
||||||
public DbSet<CustomComponent> CustomComponents { get; set; }
|
public DbSet<CustomComponent> CustomComponents { get; set; }
|
||||||
public DbSet<DynamicService> DynamicServices { get; set; }
|
public DbSet<DynamicService> DynamicServices { get; set; }
|
||||||
public DbSet<ReportTemplate> ReportTemplates { get; set; }
|
public DbSet<ReportTemplate> ReportTemplates { get; set; }
|
||||||
public DbSet<ReportParameter> ReportParameters { get; set; }
|
|
||||||
public DbSet<ReportGenerated> ReportGenerated { get; set; }
|
|
||||||
public DbSet<ReportCategory> ReportCategories { get; set; }
|
public DbSet<ReportCategory> ReportCategories { get; set; }
|
||||||
public DbSet<Note> Activities { get; set; }
|
public DbSet<Note> Activities { get; set; }
|
||||||
public DbSet<IpRestriction> IpRestrictions { get; set; }
|
public DbSet<IpRestriction> IpRestrictions { get; set; }
|
||||||
|
|
@ -844,42 +842,7 @@ public class PlatformDbContext :
|
||||||
b.Property(x => x.Name).IsRequired().HasMaxLength(256);
|
b.Property(x => x.Name).IsRequired().HasMaxLength(256);
|
||||||
b.Property(x => x.Description).HasMaxLength(1024);
|
b.Property(x => x.Description).HasMaxLength(1024);
|
||||||
b.Property(x => x.HtmlContent).IsRequired();
|
b.Property(x => x.HtmlContent).IsRequired();
|
||||||
b.Property(x => x.Tags).HasMaxLength(2048);
|
b.Property(x => x.Status).HasMaxLength(20);
|
||||||
|
|
||||||
b.HasMany(t => t.Parameters)
|
|
||||||
.WithOne(p => p.ReportTemplate)
|
|
||||||
.HasForeignKey(p => p.TemplateId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
b.HasMany(t => t.Generated)
|
|
||||||
.WithOne(p => p.ReportTemplate)
|
|
||||||
.HasForeignKey(p => p.TemplateId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Entity<ReportParameter>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ReportParameter)), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.TemplateId).IsRequired();
|
|
||||||
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
|
|
||||||
b.Property(x => x.Placeholder).HasMaxLength(256);
|
|
||||||
b.Property(x => x.Type).IsRequired();
|
|
||||||
b.Property(x => x.DefaultValue).HasMaxLength(512);
|
|
||||||
b.Property(x => x.Required).IsRequired();
|
|
||||||
b.Property(x => x.Description).HasMaxLength(1024);
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Entity<ReportGenerated>(b =>
|
|
||||||
{
|
|
||||||
b.ToTable(TableNameResolver.GetFullTableName(nameof(TableNameEnum.ReportGenerated)), Prefix.DbSchema);
|
|
||||||
b.ConfigureByConvention();
|
|
||||||
|
|
||||||
b.Property(x => x.TemplateId).IsRequired(false);
|
|
||||||
b.Property(x => x.TemplateName).IsRequired().HasMaxLength(256);
|
|
||||||
b.Property(x => x.GeneratedContent).IsRequired();
|
|
||||||
b.Property(x => x.Parameters).HasMaxLength(4096); // JSON string
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//Administration
|
//Administration
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
||||||
namespace Erp.Platform.Migrations
|
namespace Erp.Platform.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PlatformDbContext))]
|
[DbContext(typeof(PlatformDbContext))]
|
||||||
[Migration("20260107073550_Initial")]
|
[Migration("20260107104555_Initial")]
|
||||||
partial class Initial
|
partial class Initial
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|
@ -12877,141 +12877,6 @@ namespace Erp.Platform.Migrations
|
||||||
b.ToTable("Sas_T_ReportCategory", (string)null);
|
b.ToTable("Sas_T_ReportCategory", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportGenerated", 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>("GeneratedContent")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
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>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TemplateId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("TemplateName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("TemplateId");
|
|
||||||
|
|
||||||
b.ToTable("Sas_T_ReportGenerated", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportParameter", 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>("DefaultValue")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("nvarchar(512)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
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(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Placeholder")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("Required")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<Guid>("TemplateId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.Property<string>("Type")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("TemplateId");
|
|
||||||
|
|
||||||
b.ToTable("Sas_T_ReportParameter", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -13063,9 +12928,9 @@ namespace Erp.Platform.Migrations
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("nvarchar(256)");
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
b.Property<string>("Tags")
|
b.Property<string>("Status")
|
||||||
.HasMaxLength(2048)
|
.HasMaxLength(20)
|
||||||
.HasColumnType("nvarchar(2048)");
|
.HasColumnType("nvarchar(20)");
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
b.Property<Guid?>("TenantId")
|
||||||
.HasColumnType("uniqueidentifier")
|
.HasColumnType("uniqueidentifier")
|
||||||
|
|
@ -21748,27 +21613,6 @@ namespace Erp.Platform.Migrations
|
||||||
b.Navigation("Branch");
|
b.Navigation("Branch");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportGenerated", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Erp.Platform.Entities.ReportTemplate", "ReportTemplate")
|
|
||||||
.WithMany("Generated")
|
|
||||||
.HasForeignKey("TemplateId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
b.Navigation("ReportTemplate");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportParameter", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Erp.Platform.Entities.ReportTemplate", "ReportTemplate")
|
|
||||||
.WithMany("Parameters")
|
|
||||||
.HasForeignKey("TemplateId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("ReportTemplate");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Erp.Platform.Entities.ReportCategory", "ReportCategory")
|
b.HasOne("Erp.Platform.Entities.ReportCategory", "ReportCategory")
|
||||||
|
|
@ -22958,13 +22802,6 @@ namespace Erp.Platform.Migrations
|
||||||
b.Navigation("ReportTemplates");
|
b.Navigation("ReportTemplates");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Generated");
|
|
||||||
|
|
||||||
b.Navigation("Parameters");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.Request", b =>
|
modelBuilder.Entity("Erp.Platform.Entities.Request", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Items");
|
b.Navigation("Items");
|
||||||
|
|
@ -4479,7 +4479,7 @@ namespace Erp.Platform.Migrations
|
||||||
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, nullable: true),
|
||||||
HtmlContent = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
HtmlContent = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
CategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
Tags = table.Column<string>(type: "nvarchar(2048)", maxLength: 2048, nullable: true),
|
Status = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
|
||||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
|
@ -4873,67 +4873,6 @@ namespace Erp.Platform.Migrations
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Sas_T_ReportGenerated",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
TemplateId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
TemplateName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
|
|
||||||
GeneratedContent = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
|
||||||
Parameters = table.Column<string>(type: "nvarchar(max)", maxLength: 4096, 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_Sas_T_ReportGenerated", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Sas_T_ReportGenerated_Sas_T_ReportTemplate_TemplateId",
|
|
||||||
column: x => x.TemplateId,
|
|
||||||
principalTable: "Sas_T_ReportTemplate",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Sas_T_ReportParameter",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
|
||||||
TemplateId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
|
||||||
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
|
|
||||||
Placeholder = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
|
|
||||||
Type = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
|
||||||
DefaultValue = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true),
|
|
||||||
Required = table.Column<bool>(type: "bit", nullable: false),
|
|
||||||
Description = table.Column<string>(type: "nvarchar(1024)", maxLength: 1024, 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_Sas_T_ReportParameter", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Sas_T_ReportParameter_Sas_T_ReportTemplate_TemplateId",
|
|
||||||
column: x => x.TemplateId,
|
|
||||||
principalTable: "Sas_T_ReportTemplate",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Cascade);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Sas_H_District",
|
name: "Sas_H_District",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
|
@ -9742,16 +9681,6 @@ namespace Erp.Platform.Migrations
|
||||||
table: "Sas_T_CustomEntityField",
|
table: "Sas_T_CustomEntityField",
|
||||||
column: "EntityId");
|
column: "EntityId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Sas_T_ReportGenerated_TemplateId",
|
|
||||||
table: "Sas_T_ReportGenerated",
|
|
||||||
column: "TemplateId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Sas_T_ReportParameter_TemplateId",
|
|
||||||
table: "Sas_T_ReportParameter",
|
|
||||||
column: "TemplateId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Sas_T_ReportTemplate_CategoryId",
|
name: "IX_Sas_T_ReportTemplate_CategoryId",
|
||||||
table: "Sas_T_ReportTemplate",
|
table: "Sas_T_ReportTemplate",
|
||||||
|
|
@ -10766,10 +10695,7 @@ namespace Erp.Platform.Migrations
|
||||||
name: "Sas_T_Note");
|
name: "Sas_T_Note");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_T_ReportGenerated");
|
name: "Sas_T_ReportTemplate");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Sas_T_ReportParameter");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Scp_T_ApprovalStep");
|
name: "Scp_T_ApprovalStep");
|
||||||
|
|
@ -10940,7 +10866,7 @@ namespace Erp.Platform.Migrations
|
||||||
name: "Sas_T_CustomEntity");
|
name: "Sas_T_CustomEntity");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_T_ReportTemplate");
|
name: "Sas_T_ReportCategory");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Scp_T_Approval");
|
name: "Scp_T_Approval");
|
||||||
|
|
@ -11041,9 +10967,6 @@ namespace Erp.Platform.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Sas_H_ListForm");
|
name: "Sas_H_ListForm");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Sas_T_ReportCategory");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Scp_T_Quotation");
|
name: "Scp_T_Quotation");
|
||||||
|
|
||||||
|
|
@ -12874,141 +12874,6 @@ namespace Erp.Platform.Migrations
|
||||||
b.ToTable("Sas_T_ReportCategory", (string)null);
|
b.ToTable("Sas_T_ReportCategory", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportGenerated", 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>("GeneratedContent")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
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>("Parameters")
|
|
||||||
.HasMaxLength(4096)
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TemplateId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<string>("TemplateName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("TemplateId");
|
|
||||||
|
|
||||||
b.ToTable("Sas_T_ReportGenerated", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportParameter", 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>("DefaultValue")
|
|
||||||
.HasMaxLength(512)
|
|
||||||
.HasColumnType("nvarchar(512)");
|
|
||||||
|
|
||||||
b.Property<Guid?>("DeleterId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("DeleterId");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DeletionTime")
|
|
||||||
.HasColumnType("datetime2")
|
|
||||||
.HasColumnName("DeletionTime");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.HasMaxLength(1024)
|
|
||||||
.HasColumnType("nvarchar(1024)");
|
|
||||||
|
|
||||||
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(128)
|
|
||||||
.HasColumnType("nvarchar(128)");
|
|
||||||
|
|
||||||
b.Property<string>("Placeholder")
|
|
||||||
.HasMaxLength(256)
|
|
||||||
.HasColumnType("nvarchar(256)");
|
|
||||||
|
|
||||||
b.Property<bool>("Required")
|
|
||||||
.HasColumnType("bit");
|
|
||||||
|
|
||||||
b.Property<Guid>("TemplateId")
|
|
||||||
.HasColumnType("uniqueidentifier");
|
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
|
||||||
.HasColumnType("uniqueidentifier")
|
|
||||||
.HasColumnName("TenantId");
|
|
||||||
|
|
||||||
b.Property<string>("Type")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("nvarchar(max)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("TemplateId");
|
|
||||||
|
|
||||||
b.ToTable("Sas_T_ReportParameter", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -13060,9 +12925,9 @@ namespace Erp.Platform.Migrations
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("nvarchar(256)");
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
b.Property<string>("Tags")
|
b.Property<string>("Status")
|
||||||
.HasMaxLength(2048)
|
.HasMaxLength(20)
|
||||||
.HasColumnType("nvarchar(2048)");
|
.HasColumnType("nvarchar(20)");
|
||||||
|
|
||||||
b.Property<Guid?>("TenantId")
|
b.Property<Guid?>("TenantId")
|
||||||
.HasColumnType("uniqueidentifier")
|
.HasColumnType("uniqueidentifier")
|
||||||
|
|
@ -21745,27 +21610,6 @@ namespace Erp.Platform.Migrations
|
||||||
b.Navigation("Branch");
|
b.Navigation("Branch");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportGenerated", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Erp.Platform.Entities.ReportTemplate", "ReportTemplate")
|
|
||||||
.WithMany("Generated")
|
|
||||||
.HasForeignKey("TemplateId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
b.Navigation("ReportTemplate");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportParameter", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("Erp.Platform.Entities.ReportTemplate", "ReportTemplate")
|
|
||||||
.WithMany("Parameters")
|
|
||||||
.HasForeignKey("TemplateId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("ReportTemplate");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Erp.Platform.Entities.ReportCategory", "ReportCategory")
|
b.HasOne("Erp.Platform.Entities.ReportCategory", "ReportCategory")
|
||||||
|
|
@ -22955,13 +22799,6 @@ namespace Erp.Platform.Migrations
|
||||||
b.Navigation("ReportTemplates");
|
b.Navigation("ReportTemplates");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.ReportTemplate", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Generated");
|
|
||||||
|
|
||||||
b.Navigation("Parameters");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("Erp.Platform.Entities.Request", b =>
|
modelBuilder.Entity("Erp.Platform.Entities.Request", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Items");
|
b.Navigation("Items");
|
||||||
|
|
|
||||||
|
|
@ -103,23 +103,6 @@
|
||||||
"dependencies": ["DynamicEntityComponent"]
|
"dependencies": ["DynamicEntityComponent"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ReportCategories": [
|
|
||||||
{
|
|
||||||
"name": "Genel Raporlar",
|
|
||||||
"description": "Şirket içi genel tüm raporlar",
|
|
||||||
"icon": "📊"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Taahhütnameler",
|
|
||||||
"description": "Kursiyeler ile ilgili taahhütname raporları",
|
|
||||||
"icon": "✍️"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Sözleşmeler",
|
|
||||||
"description": "Tedarikçiler ile ilgili sözleşme raporları",
|
|
||||||
"icon": "📜"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Abouts": [
|
"Abouts": [
|
||||||
{
|
{
|
||||||
"stats": [
|
"stats": [
|
||||||
|
|
@ -6636,5 +6619,31 @@
|
||||||
"description": "Üretim siparişi beklemede",
|
"description": "Üretim siparişi beklemede",
|
||||||
"isActive": true
|
"isActive": true
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"ReportCategories": [
|
||||||
|
{
|
||||||
|
"name": "Genel Raporlar",
|
||||||
|
"description": "Şirket içi genel tüm raporlar",
|
||||||
|
"icon": "📊"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Taahhütnameler",
|
||||||
|
"description": "Kursiyeler ile ilgili taahhütname raporları",
|
||||||
|
"icon": "✍️"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sözleşmeler",
|
||||||
|
"description": "Tedarikçiler ile ilgili sözleşme raporları",
|
||||||
|
"icon": "📜"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ReportTemplates": [
|
||||||
|
{
|
||||||
|
"name": "Standard Taahhütname",
|
||||||
|
"description": "Standard Taahhütname",
|
||||||
|
"categoryName": "Taahhütnameler",
|
||||||
|
"htmlContent": "<h1>Taahhütname</h1><p>Bu belge, tarafların belirli yükümlülüklerini ve taahhütlerini belirtir.</p>",
|
||||||
|
"status": "Aktif"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
private readonly IRepository<CustomEndpoint, Guid> _customEndpointRepository;
|
private readonly IRepository<CustomEndpoint, Guid> _customEndpointRepository;
|
||||||
private readonly IRepository<CustomComponent, Guid> _customComponentRepository;
|
private readonly IRepository<CustomComponent, Guid> _customComponentRepository;
|
||||||
private readonly IRepository<ReportCategory, Guid> _reportCategoriesRepository;
|
private readonly IRepository<ReportCategory, Guid> _reportCategoriesRepository;
|
||||||
|
private readonly IRepository<ReportTemplate, Guid> _reportTemplatesRepository;
|
||||||
private readonly IRepository<About, Guid> _aboutRepository;
|
private readonly IRepository<About, Guid> _aboutRepository;
|
||||||
private readonly IRepository<Product, Guid> _productRepository;
|
private readonly IRepository<Product, Guid> _productRepository;
|
||||||
private readonly IRepository<PaymentMethod, string> _paymentMethodRepository;
|
private readonly IRepository<PaymentMethod, string> _paymentMethodRepository;
|
||||||
|
|
@ -170,6 +171,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
IRepository<CustomEndpoint, Guid> customEndpointRepository,
|
IRepository<CustomEndpoint, Guid> customEndpointRepository,
|
||||||
IRepository<CustomComponent, Guid> customComponentRepository,
|
IRepository<CustomComponent, Guid> customComponentRepository,
|
||||||
IRepository<ReportCategory, Guid> reportCategoriesRepository,
|
IRepository<ReportCategory, Guid> reportCategoriesRepository,
|
||||||
|
IRepository<ReportTemplate, Guid> reportTemplatesRepository,
|
||||||
IRepository<About, Guid> aboutRepository,
|
IRepository<About, Guid> aboutRepository,
|
||||||
IRepository<Service, Guid> servicesRepository,
|
IRepository<Service, Guid> servicesRepository,
|
||||||
IRepository<Product, Guid> productRepository,
|
IRepository<Product, Guid> productRepository,
|
||||||
|
|
@ -313,6 +315,7 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
_installmentOptionRepository = installmentOptionRepository;
|
_installmentOptionRepository = installmentOptionRepository;
|
||||||
_customComponentRepository = customComponentRepository;
|
_customComponentRepository = customComponentRepository;
|
||||||
_reportCategoriesRepository = reportCategoriesRepository;
|
_reportCategoriesRepository = reportCategoriesRepository;
|
||||||
|
_reportTemplatesRepository = reportTemplatesRepository;
|
||||||
_servicesRepository = servicesRepository;
|
_servicesRepository = servicesRepository;
|
||||||
_aboutRepository = aboutRepository;
|
_aboutRepository = aboutRepository;
|
||||||
_contactRepository = contactRepository;
|
_contactRepository = contactRepository;
|
||||||
|
|
@ -2951,6 +2954,24 @@ public class TenantDataSeeder : IDataSeedContributor, ITransientDependency
|
||||||
IsActive = item.IsActive
|
IsActive = item.IsActive
|
||||||
}, autoSave: true);
|
}, autoSave: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var item in items.ReportTemplates)
|
||||||
|
{
|
||||||
|
var exists = await _reportTemplatesRepository.AnyAsync(x => x.Name == item.Name);
|
||||||
|
if (exists)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var category = await _reportCategoriesRepository.FirstOrDefaultAsync(x => x.Name == item.CategoryName);
|
||||||
|
|
||||||
|
await _reportTemplatesRepository.InsertAsync(new ReportTemplate(
|
||||||
|
Guid.NewGuid(),
|
||||||
|
item.Name,
|
||||||
|
item.Description,
|
||||||
|
item.HtmlContent,
|
||||||
|
category.Id,
|
||||||
|
item.Status
|
||||||
|
), autoSave: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,18 @@ public class TenantSeederDto
|
||||||
public List<ProductionOrderTypeSeedDto> ProductionOrderTypes { get; set; }
|
public List<ProductionOrderTypeSeedDto> ProductionOrderTypes { get; set; }
|
||||||
public List<ProductionOrderStatusSeedDto> ProductionOrderStatuses { get; set; }
|
public List<ProductionOrderStatusSeedDto> ProductionOrderStatuses { get; set; }
|
||||||
public List<ProductionWorkorderStatusSeedDto> ProductionWorkorderStatuses { get; set; }
|
public List<ProductionWorkorderStatusSeedDto> ProductionWorkorderStatuses { get; set; }
|
||||||
|
|
||||||
|
//Report Templates
|
||||||
|
public List<ReportTemplateSeedDto> ReportTemplates { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ReportTemplateSeedDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string CategoryName { get; set; }
|
||||||
|
public string HtmlContent { get; set; }
|
||||||
|
public string Status { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ProductionWorkorderStatusSeedDto
|
public class ProductionWorkorderStatusSeedDto
|
||||||
|
|
|
||||||
|
|
@ -1,322 +0,0 @@
|
||||||
import React, { useState, useMemo, useEffect } from 'react'
|
|
||||||
import { TemplateEditor } from '../reports/TemplateEditor'
|
|
||||||
import { ReportGenerator } from '../reports/ReportGenerator'
|
|
||||||
import { TemplateCard } from './TemplateCard'
|
|
||||||
import { Button, Input } from '../ui'
|
|
||||||
import { FaPlus, FaSearch, FaFilter, FaFileAlt, FaChartBar } from 'react-icons/fa'
|
|
||||||
import { ReportCategoryDto, ReportTemplateDto } from '@/proxy/reports/models'
|
|
||||||
import { useReports } from '@/utils/hooks/useReports'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
|
|
||||||
export const Dashboard: React.FC = () => {
|
|
||||||
const {
|
|
||||||
templates,
|
|
||||||
categories,
|
|
||||||
isLoading,
|
|
||||||
createTemplate,
|
|
||||||
updateTemplate,
|
|
||||||
deleteTemplate,
|
|
||||||
generateReport,
|
|
||||||
} = useReports()
|
|
||||||
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
|
|
||||||
const tumuCategory = useMemo(
|
|
||||||
() => ({
|
|
||||||
id: 'tumu-category',
|
|
||||||
name: translate('::App.Reports.Dashboard.All'),
|
|
||||||
description: translate('::App.Reports.Dashboard.AllDescription'),
|
|
||||||
icon: '📋',
|
|
||||||
}),
|
|
||||||
[translate],
|
|
||||||
)
|
|
||||||
|
|
||||||
const [showEditor, setShowEditor] = useState(false)
|
|
||||||
const [showGenerator, setShowGenerator] = useState(false)
|
|
||||||
const [editingTemplate, setEditingTemplate] = useState<ReportTemplateDto | null>(null)
|
|
||||||
const [generatingTemplate, setGeneratingTemplate] = useState<ReportTemplateDto | null>(null)
|
|
||||||
const [searchQuery, setSearchQuery] = useState('')
|
|
||||||
const [selectedCategory, setSelectedCategory] = useState<ReportCategoryDto | null>(null)
|
|
||||||
|
|
||||||
// Set initial selected category to tumuCategory
|
|
||||||
useEffect(() => {
|
|
||||||
if (!selectedCategory) {
|
|
||||||
setSelectedCategory(tumuCategory)
|
|
||||||
}
|
|
||||||
}, [tumuCategory, selectedCategory])
|
|
||||||
|
|
||||||
// Create category options with "tumu-category" at the top
|
|
||||||
const categoryOptions = useMemo(() => {
|
|
||||||
const categoryNames = [tumuCategory, ...categories.map((cat) => cat)]
|
|
||||||
return categoryNames
|
|
||||||
}, [categories, tumuCategory])
|
|
||||||
|
|
||||||
// Filter templates based on selected category and search query
|
|
||||||
const filteredTemplates = useMemo(() => {
|
|
||||||
let filtered = templates
|
|
||||||
|
|
||||||
// Filter by category (if not "tumu-category")
|
|
||||||
if (selectedCategory && selectedCategory.id !== 'tumu-category') {
|
|
||||||
filtered = filtered.filter((template) => template.categoryId === selectedCategory.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter by search query
|
|
||||||
if (searchQuery) {
|
|
||||||
filtered = filtered.filter((template) => {
|
|
||||||
const matchesSearch =
|
|
||||||
template.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
||||||
template.description?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
||||||
template.tags.some((tag: any) => tag.toLowerCase().includes(searchQuery.toLowerCase()))
|
|
||||||
|
|
||||||
return matchesSearch
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered
|
|
||||||
}, [templates, selectedCategory, searchQuery])
|
|
||||||
|
|
||||||
// Calculate total parameters
|
|
||||||
const totalParameters = useMemo(() => {
|
|
||||||
return filteredTemplates.reduce((sum, template) => {
|
|
||||||
return sum + (Array.isArray(template.parameters) ? template.parameters.length : 0)
|
|
||||||
}, 0)
|
|
||||||
}, [filteredTemplates])
|
|
||||||
|
|
||||||
const handleCreateTemplate = () => {
|
|
||||||
setEditingTemplate(null)
|
|
||||||
setShowEditor(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleEditTemplate = (template: ReportTemplateDto) => {
|
|
||||||
setEditingTemplate(template)
|
|
||||||
setShowEditor(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSaveTemplate = async (templateData: ReportTemplateDto) => {
|
|
||||||
try {
|
|
||||||
if (editingTemplate) {
|
|
||||||
await updateTemplate(editingTemplate.id, templateData)
|
|
||||||
} else {
|
|
||||||
await createTemplate(templateData)
|
|
||||||
}
|
|
||||||
setShowEditor(false)
|
|
||||||
setEditingTemplate(null)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error saving template:', error)
|
|
||||||
// Handle error - could show toast notification
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeleteTemplate = async (id: string) => {
|
|
||||||
if (window.confirm(translate('::App.Reports.Dashboard.DeleteTemplateConfirmation'))) {
|
|
||||||
try {
|
|
||||||
await deleteTemplate(id)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error deleting template:', error)
|
|
||||||
// Handle error - could show toast notification
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleGenerateReport = (template: ReportTemplateDto) => {
|
|
||||||
setGeneratingTemplate(template)
|
|
||||||
setShowGenerator(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleReportGeneration = async (
|
|
||||||
templateId: string,
|
|
||||||
parameters: Record<string, string>,
|
|
||||||
): Promise<string | null> => {
|
|
||||||
try {
|
|
||||||
const report = await generateReport(templateId, parameters)
|
|
||||||
return report ? report.id : null
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating report:', error)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isLoading ? (
|
|
||||||
<div className="flex items-center justify-center min-h-96">
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
|
|
||||||
<p className="text-gray-600">{translate('::App.Loading')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col lg:flex-row gap-8">
|
|
||||||
{/* Left Sidebar - Categories */}
|
|
||||||
<div className="lg:w-64 flex-shrink-0 p-4 bg-gray-50">
|
|
||||||
<nav className="space-y-2">
|
|
||||||
{categoryOptions.map((category) => {
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={category.id}
|
|
||||||
onClick={() => setSelectedCategory(category)}
|
|
||||||
className={`w-full flex items-center space-x-3 p-2 rounded-lg text-left transition-colors ${
|
|
||||||
selectedCategory?.id === category.id
|
|
||||||
? 'bg-blue-100 text-blue-700'
|
|
||||||
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
{category.icon && <span className="text-lg">{category.icon}</span>}
|
|
||||||
<span className="font-medium">{category.name}</span>
|
|
||||||
</div>
|
|
||||||
{category.id !== 'tumu-category' && (
|
|
||||||
<span className="text-sm text-gray-500 ml-2">
|
|
||||||
({templates.filter((t) => t.categoryId === category.id).length})
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{category.id === 'tumu-category' && (
|
|
||||||
<span className="text-sm text-gray-500 ml-2">({templates.length})</span>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Main Content */}
|
|
||||||
<div className="flex-1">
|
|
||||||
<div className="flex items-center justify-between mb-4">
|
|
||||||
<div className="flex-1">
|
|
||||||
<h2 className="text-2xl font-bold text-gray-900">
|
|
||||||
{translate('::' + selectedCategory?.name)}
|
|
||||||
</h2>
|
|
||||||
<div className="text-sm text-gray-500 ml-1">
|
|
||||||
{translate('::' + selectedCategory?.description)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-4">
|
|
||||||
{/* Search Input */}
|
|
||||||
<div className="relative">
|
|
||||||
<FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-400" />
|
|
||||||
<Input
|
|
||||||
placeholder={translate('::App.Reports.Dashboard.SearchTemplate')}
|
|
||||||
value={searchQuery}
|
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
|
||||||
className="pl-10 w-64"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* New Template Button */}
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
onClick={handleCreateTemplate}
|
|
||||||
className="bg-blue-600 hover:bg-blue-700 font-medium px-6 py-2.5 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 flex items-center space-x-2"
|
|
||||||
>
|
|
||||||
<FaPlus className="h-5 w-5" />
|
|
||||||
<span>{translate('::App.Reports.Dashboard.NewTemplate')}</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Stats */}
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
|
|
||||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-200">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<p className="text-sm font-medium text-gray-600">
|
|
||||||
{selectedCategory?.id === 'tumu-category'
|
|
||||||
? translate('::App.Reports.Dashboard.TotalTemplates')
|
|
||||||
: translate('::App.Reports.Dashboard.CategoryTemplates')}
|
|
||||||
</p>
|
|
||||||
<p className="text-2xl font-bold text-gray-900">{filteredTemplates.length}</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-blue-100 p-3 rounded-full">
|
|
||||||
<FaFileAlt className="h-6 w-6 text-blue-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-200">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<p className="text-sm font-medium text-gray-600">
|
|
||||||
{translate('::App.Reports.Dashboard.ActiveCategories')}
|
|
||||||
</p>
|
|
||||||
<p className="text-2xl font-bold text-gray-900">{categories.length}</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-emerald-100 p-3 rounded-full">
|
|
||||||
<FaFilter className="h-6 w-6 text-emerald-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-xl shadow-md p-6 border border-gray-200">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div>
|
|
||||||
<p className="text-sm font-medium text-gray-600">
|
|
||||||
{selectedCategory?.id === 'tumu-category'
|
|
||||||
? translate('::App.Reports.Dashboard.TotalParameters')
|
|
||||||
: translate('::App.Reports.Dashboard.CategoryParameters')}
|
|
||||||
</p>
|
|
||||||
<p className="text-2xl font-bold text-gray-900">{totalParameters}</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-purple-100 p-3 rounded-full">
|
|
||||||
<FaChartBar className="h-6 w-6 text-purple-600" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Templates Grid */}
|
|
||||||
{filteredTemplates.length === 0 ? (
|
|
||||||
<div className="bg-white rounded-xl shadow-md p-12 border border-gray-200 text-center">
|
|
||||||
<FaFileAlt className="h-16 w-16 text-gray-400 mx-auto mb-4" />
|
|
||||||
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
|
||||||
{templates.length === 0 ? 'Henüz şablon oluşturulmamış' : 'Şablon bulunamadı'}
|
|
||||||
</h3>
|
|
||||||
<p className="text-gray-500 mb-6">
|
|
||||||
{templates.length === 0
|
|
||||||
? translate('::App.Reports.Dashboard.CreateFirstTemplate')
|
|
||||||
: translate('::App.Reports.Dashboard.NoSearchResults')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
||||||
{filteredTemplates.map((template) => (
|
|
||||||
<TemplateCard
|
|
||||||
key={template.id}
|
|
||||||
template={template}
|
|
||||||
categories={categories}
|
|
||||||
onEdit={handleEditTemplate}
|
|
||||||
onDelete={handleDeleteTemplate}
|
|
||||||
onGenerate={handleGenerateReport}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Modals */}
|
|
||||||
<TemplateEditor
|
|
||||||
isOpen={showEditor}
|
|
||||||
onClose={() => {
|
|
||||||
setShowEditor(false)
|
|
||||||
setEditingTemplate(null)
|
|
||||||
}}
|
|
||||||
onSave={handleSaveTemplate}
|
|
||||||
template={editingTemplate}
|
|
||||||
categories={categories}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ReportGenerator
|
|
||||||
isOpen={showGenerator}
|
|
||||||
onClose={() => {
|
|
||||||
setShowGenerator(false)
|
|
||||||
setGeneratingTemplate(null)
|
|
||||||
}}
|
|
||||||
template={generatingTemplate}
|
|
||||||
categories={categories}
|
|
||||||
onGenerate={handleReportGeneration}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
||||||
import React, { useState } from 'react'
|
|
||||||
import { Button, Input, Dialog } from '../ui'
|
|
||||||
import { FaFileAlt } from 'react-icons/fa'
|
|
||||||
import { ReportCategoryDto, ReportTemplateDto } from '@/proxy/reports/models'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
|
||||||
|
|
||||||
interface ReportGeneratorProps {
|
|
||||||
isOpen: boolean
|
|
||||||
onClose: () => void
|
|
||||||
template: ReportTemplateDto | null
|
|
||||||
categories: ReportCategoryDto[]
|
|
||||||
onGenerate: (templateId: string, parameters: Record<string, string>) => Promise<string | null> // Rapor ID'si döndürmek için (async)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ReportGenerator: React.FC<ReportGeneratorProps> = ({
|
|
||||||
isOpen,
|
|
||||||
onClose,
|
|
||||||
template,
|
|
||||||
categories,
|
|
||||||
onGenerate,
|
|
||||||
}) => {
|
|
||||||
const [parameterValues, setParameterValues] = useState<Record<string, string>>({})
|
|
||||||
const [isGenerating, setIsGenerating] = useState(false)
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
|
|
||||||
// const [showPrintPreview, setShowPrintPreview] = useState(false);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (template && isOpen) {
|
|
||||||
const initialValues: Record<string, string> = {}
|
|
||||||
template.parameters.forEach((param) => {
|
|
||||||
initialValues[param.name] = param.defaultValue || ''
|
|
||||||
})
|
|
||||||
setParameterValues(initialValues)
|
|
||||||
}
|
|
||||||
}, [template, isOpen])
|
|
||||||
|
|
||||||
const handleParameterChange = (paramName: string, value: string) => {
|
|
||||||
setParameterValues((prev) => ({
|
|
||||||
...prev,
|
|
||||||
[paramName]: value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleGenerateAndShow = async () => {
|
|
||||||
if (!template) return
|
|
||||||
|
|
||||||
setIsGenerating(true)
|
|
||||||
try {
|
|
||||||
// Rapor oluştur ve ID'yi al
|
|
||||||
const reportId = await onGenerate(template.id, parameterValues)
|
|
||||||
|
|
||||||
if (reportId) {
|
|
||||||
// Yeni sekmede rapor URL'sini aç
|
|
||||||
const reportUrl = ROUTES_ENUM.protected.saas.reports.view.replace(':id', reportId)
|
|
||||||
window.open(reportUrl, '_blank')
|
|
||||||
onClose() // Modal'ı kapat
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error generating report:', error)
|
|
||||||
// Handle error - could show toast notification
|
|
||||||
} finally {
|
|
||||||
setIsGenerating(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!template) return null
|
|
||||||
|
|
||||||
const isValid = template.parameters.every(
|
|
||||||
(param) =>
|
|
||||||
!param.required || (parameterValues[param.name] && parameterValues[param.name].trim()),
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Dialog isOpen={isOpen} onClose={onClose} width="60%">
|
|
||||||
<h5 className="mb-4">{`${template.name} - ${translate('::App.Reports.ReportGenerator.ReportParameters')}`}</h5>
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div className="bg-gray-50 p-4 rounded-lg">
|
|
||||||
<h3 className="font-medium text-gray-900 mb-2">{template.name}</h3>
|
|
||||||
<p className="text-gray-600 text-sm">{template.description}</p>
|
|
||||||
<div className="flex items-center mt-2 space-x-2">
|
|
||||||
<span className="text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded">
|
|
||||||
{categories.find((c) => c.id === template.categoryId)?.name}
|
|
||||||
</span>
|
|
||||||
{template.tags.map((tag) => (
|
|
||||||
<span key={tag} className="text-xs bg-gray-100 text-gray-800 px-2 py-1 rounded">
|
|
||||||
{tag}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{template.parameters.length > 0 ? (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h4 className="font-medium text-gray-900">
|
|
||||||
{translate('::App.Reports.ReportGenerator.ParameterValues')}
|
|
||||||
</h4>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
{template.parameters.map((param) => (
|
|
||||||
<Input
|
|
||||||
key={param.id}
|
|
||||||
type={param.type}
|
|
||||||
value={parameterValues[param.name] || ''}
|
|
||||||
onChange={(e) => handleParameterChange(param.name, e.target.value)}
|
|
||||||
placeholder={`${param.name} ${param.required ? '*' : ''}`}
|
|
||||||
title={param.description}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
{template.parameters.some((p) => p.required) && (
|
|
||||||
<p className="text-sm text-gray-500">
|
|
||||||
{translate('::App.Reports.ReportGenerator.RequiredFieldsNote')}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="py-8 text-gray-500">
|
|
||||||
<FaFileAlt className="h-12 w-12 text-gray-400 mx-auto mb-4" />
|
|
||||||
<p>{translate('::App.Reports.ReportGenerator.NoParameters')}</p>
|
|
||||||
<p className="text-sm">{translate('::App.Reports.ReportGenerator.DirectGenerate')}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex justify-end space-x-3">
|
|
||||||
<Button onClick={onClose} disabled={isGenerating}>
|
|
||||||
{translate('::Cancel')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
onClick={handleGenerateAndShow}
|
|
||||||
disabled={!isValid || isGenerating}
|
|
||||||
className="bg-blue-600 hover:bg-blue-700 font-medium px-2 sm:px-3 py-1.5 rounded text-xs flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<FaFileAlt className="h-4 w-4 mr-2" />
|
|
||||||
{isGenerating
|
|
||||||
? translate('::App.DeveloperKit.Migration.Generating')
|
|
||||||
: translate('::App.Reports.ReportGenerator.GenerateReport')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import { HtmlEditor, ImageUpload, Item, MediaResizing, Toolbar } from 'devextreme-react/html-editor'
|
|
||||||
import 'devextreme/dist/css/dx.light.css'
|
|
||||||
import {
|
|
||||||
fontFamilyOptions,
|
|
||||||
fontSizeOptions,
|
|
||||||
fontValues,
|
|
||||||
headerOptions,
|
|
||||||
headerValues,
|
|
||||||
sizeValues,
|
|
||||||
} from '@/proxy/reports/data'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
|
|
||||||
interface ReportHtmlEditorProps {
|
|
||||||
value: string
|
|
||||||
onChange: (value: string) => void
|
|
||||||
placeholder?: string
|
|
||||||
height?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ReportHtmlEditor: React.FC<ReportHtmlEditorProps> = ({
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
height = '100%',
|
|
||||||
}) => {
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col space-y-2" style={{ height }}>
|
|
||||||
<HtmlEditor
|
|
||||||
value={value}
|
|
||||||
onValueChanged={(e) => onChange(e.value)}
|
|
||||||
height={height || '400px'}
|
|
||||||
placeholder={translate('::App.Reports.ReportHtmlViewer.Placeholder')}
|
|
||||||
>
|
|
||||||
<MediaResizing enabled={true} />
|
|
||||||
<ImageUpload fileUploadMode="base64" />
|
|
||||||
<Toolbar multiline={true}>
|
|
||||||
<Item name="undo" />
|
|
||||||
<Item name="redo" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="size" acceptedValues={sizeValues} options={fontSizeOptions} />
|
|
||||||
<Item name="font" acceptedValues={fontValues} options={fontFamilyOptions} />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="bold" />
|
|
||||||
<Item name="italic" />
|
|
||||||
<Item name="strike" />
|
|
||||||
<Item name="underline" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="alignLeft" />
|
|
||||||
<Item name="alignCenter" />
|
|
||||||
<Item name="alignRight" />
|
|
||||||
<Item name="alignJustify" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="orderedList" />
|
|
||||||
<Item name="bulletList" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="header" acceptedValues={headerValues} options={headerOptions} />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="color" />
|
|
||||||
<Item name="background" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="link" />
|
|
||||||
<Item name="image" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="clear" />
|
|
||||||
<Item name="codeBlock" />
|
|
||||||
<Item name="blockquote" />
|
|
||||||
<Item name="separator" />
|
|
||||||
<Item name="insertTable" />
|
|
||||||
<Item name="deleteTable" />
|
|
||||||
<Item name="insertRowAbove" />
|
|
||||||
<Item name="insertRowBelow" />
|
|
||||||
<Item name="deleteRow" />
|
|
||||||
<Item name="insertColumnLeft" />
|
|
||||||
<Item name="insertColumnRight" />
|
|
||||||
<Item name="deleteColumn" />
|
|
||||||
</Toolbar>
|
|
||||||
</HtmlEditor>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,509 +0,0 @@
|
||||||
import React, { useState, useEffect, useMemo, useCallback } from 'react'
|
|
||||||
import { useParams, useNavigate } from 'react-router-dom'
|
|
||||||
import { Button } from '../ui/Button'
|
|
||||||
import {
|
|
||||||
FaArrowLeft,
|
|
||||||
FaCalendarAlt,
|
|
||||||
FaFileAlt,
|
|
||||||
FaDownload,
|
|
||||||
FaSearchPlus,
|
|
||||||
FaSearchMinus,
|
|
||||||
} from 'react-icons/fa'
|
|
||||||
import { ReportGeneratedDto, ReportTemplateDto } from '@/proxy/reports/models'
|
|
||||||
import { useReports } from '@/utils/hooks/useReports'
|
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
|
|
||||||
export const ReportViewer: React.FC = () => {
|
|
||||||
const { id } = useParams<{ id: string }>()
|
|
||||||
const navigate = useNavigate()
|
|
||||||
const [zoomLevel, setZoomLevel] = useState(100)
|
|
||||||
const [report, setReport] = useState<ReportGeneratedDto | null>(null)
|
|
||||||
const [template, setTemplate] = useState<ReportTemplateDto | null>(null)
|
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
|
||||||
const [error, setError] = useState<string | null>(null)
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
const { getReportById, getTemplateById, categories } = useReports()
|
|
||||||
|
|
||||||
// İçeriği sayfalara bölen fonksiyon
|
|
||||||
const splitContentIntoPages = (content: string) => {
|
|
||||||
// Basit olarak içeriği paragraf ve tablo bazında bölelim
|
|
||||||
const tempDiv = document.createElement('div')
|
|
||||||
tempDiv.innerHTML = content
|
|
||||||
|
|
||||||
const elements = Array.from(tempDiv.children)
|
|
||||||
const pages: string[] = []
|
|
||||||
let currentPage = ''
|
|
||||||
let currentPageHeight = 0
|
|
||||||
const maxPageHeight = 257 // 297mm - 40mm padding (top+bottom)
|
|
||||||
|
|
||||||
elements.forEach((element) => {
|
|
||||||
const elementHtml = element.outerHTML
|
|
||||||
// Basit yükseklik tahmini (gerçek uygulamada daha karmaşık olabilir)
|
|
||||||
let estimatedHeight = 20 // Default height
|
|
||||||
|
|
||||||
if (element.tagName === 'TABLE') {
|
|
||||||
const rows = element.querySelectorAll('tr')
|
|
||||||
estimatedHeight = rows.length * 25 // Her satır için 25mm
|
|
||||||
} else if (element.tagName.startsWith('H')) {
|
|
||||||
estimatedHeight = 15
|
|
||||||
} else if (element.tagName === 'P') {
|
|
||||||
estimatedHeight = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPageHeight + estimatedHeight > maxPageHeight && currentPage) {
|
|
||||||
pages.push(currentPage)
|
|
||||||
currentPage = elementHtml
|
|
||||||
currentPageHeight = estimatedHeight
|
|
||||||
} else {
|
|
||||||
currentPage += elementHtml
|
|
||||||
currentPageHeight += estimatedHeight
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (currentPage) {
|
|
||||||
pages.push(currentPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pages.length > 0 ? pages : [content]
|
|
||||||
}
|
|
||||||
|
|
||||||
const preloadPdfLibs = useCallback(() => {
|
|
||||||
// Hover’da ısıtma için (opsiyonel)
|
|
||||||
import('jspdf')
|
|
||||||
import('html2canvas')
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// YENİ: memoize edilmiş sayfalar
|
|
||||||
const memoizedPages = useMemo(() => {
|
|
||||||
return report ? splitContentIntoPages(report.generatedContent) : []
|
|
||||||
}, [report])
|
|
||||||
|
|
||||||
// Asenkron veri yükleme
|
|
||||||
useEffect(() => {
|
|
||||||
const loadReportData = async () => {
|
|
||||||
if (!id) {
|
|
||||||
setError("Rapor ID'si bulunamadı")
|
|
||||||
setIsLoading(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setIsLoading(true)
|
|
||||||
setError(null)
|
|
||||||
|
|
||||||
// Raporu yükle
|
|
||||||
const reportData = await getReportById(id)
|
|
||||||
|
|
||||||
if (!reportData) {
|
|
||||||
setError('Rapor bulunamadı')
|
|
||||||
setIsLoading(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setReport(reportData)
|
|
||||||
|
|
||||||
// Şablonu yükle
|
|
||||||
if (reportData.templateId) {
|
|
||||||
const templateData = await getTemplateById(reportData.templateId)
|
|
||||||
setTemplate(templateData || null)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error loading report data:', err)
|
|
||||||
setError('Rapor yüklenirken bir hata oluştu')
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadReportData()
|
|
||||||
}, [id, getReportById, getTemplateById])
|
|
||||||
|
|
||||||
// Zoom fonksiyonları
|
|
||||||
const handleZoomIn = () => {
|
|
||||||
setZoomLevel((prev) => Math.min(prev + 25, 200)) // Maksimum %200
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleZoomOut = () => {
|
|
||||||
setZoomLevel((prev) => Math.max(prev - 25, 50)) // Minimum %50
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading durumu
|
|
||||||
if (isLoading) {
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
|
|
||||||
<h2 className="text-2xl font-bold text-gray-900">
|
|
||||||
{translate('::App.Reports.ReportViewer.LoadingTitle')}
|
|
||||||
</h2>
|
|
||||||
<p className="text-gray-600">{translate('::App.Reports.ReportViewer.LoadingSubtitle')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error durumu
|
|
||||||
if (error || !id) {
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
|
||||||
<div className="text-center">
|
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">
|
|
||||||
{error || translate('::App.Reports.ReportViewer.ErrorNotFound')}
|
|
||||||
</h1>
|
|
||||||
<Button onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
|
||||||
<FaArrowLeft className="h-4 w-4 mr-2" />
|
|
||||||
Ana Sayfaya Dön
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!id) {
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
|
||||||
<div className="text-center">
|
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">
|
|
||||||
{translate('::App.Reports.ReportViewer.ErrorNotFound')}
|
|
||||||
</h1>
|
|
||||||
<Button onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
|
||||||
<FaArrowLeft className="h-4 w-4 mr-2" />
|
|
||||||
Ana Sayfaya Dön
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report yüklenmemiş ise
|
|
||||||
if (!report) {
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
|
||||||
<div className="text-center">
|
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-4">
|
|
||||||
{translate('::App.Reports.ReportViewer.ErrorNotFound')}
|
|
||||||
</h1>
|
|
||||||
<p className="text-gray-600 mb-6">
|
|
||||||
{translate('::App.Reports.ReportViewer.ErrorNotFoundDescription')}
|
|
||||||
</p>
|
|
||||||
<Button onClick={() => navigate(ROUTES_ENUM.protected.dashboard)}>
|
|
||||||
<FaArrowLeft className="h-4 w-4 mr-2" />
|
|
||||||
{translate('::Public.notFound.button')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePrint = () => {
|
|
||||||
// Yazdırma sırasında zoom seviyesini geçici olarak %100'e ayarla
|
|
||||||
const currentZoom = zoomLevel
|
|
||||||
setZoomLevel(100)
|
|
||||||
|
|
||||||
// DOM'un güncellenmesi için kısa bir gecikme
|
|
||||||
setTimeout(() => {
|
|
||||||
window.print()
|
|
||||||
|
|
||||||
// Yazdırma işlemi tamamlandıktan sonra orijinal zoom seviyesine geri dön
|
|
||||||
// Print dialog kapandıktan sonra zoom'u eski haline getir
|
|
||||||
setTimeout(() => {
|
|
||||||
setZoomLevel(currentZoom)
|
|
||||||
}, 100)
|
|
||||||
}, 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEĞİŞTİR: handleDownloadPdf
|
|
||||||
const handleDownloadPdf = async () => {
|
|
||||||
// Ağır kütüphaneleri ihtiyaç anında indir
|
|
||||||
const [jspdfMod, h2cMod] = await Promise.all([import('jspdf'), import('html2canvas')])
|
|
||||||
|
|
||||||
// jsPDF bazı dağıtımlarda default, bazılarında { jsPDF } olarak gelir
|
|
||||||
const jsPDFCtor = (jspdfMod as any).default ?? (jspdfMod as any).jsPDF
|
|
||||||
const html2canvas = (h2cMod as any).default ?? (h2cMod as any)
|
|
||||||
|
|
||||||
const pages = memoizedPages // aşağıdaki 2. adımda tanımlayacağız
|
|
||||||
|
|
||||||
try {
|
|
||||||
const pdf = new jsPDFCtor({ orientation: 'portrait', unit: 'mm', format: 'a4' })
|
|
||||||
|
|
||||||
for (let i = 0; i < pages.length; i++) {
|
|
||||||
const elementId = i === 0 ? 'report-content' : `report-content-page-${i + 1}`
|
|
||||||
const element = document.getElementById(elementId)
|
|
||||||
if (!element) continue
|
|
||||||
|
|
||||||
// Yakalama öncesi zoom’u etkisizleştir (transform varsa kalite düşmesin)
|
|
||||||
const container = element.parentElement as HTMLElement | null
|
|
||||||
const prevTransform = container?.style.transform
|
|
||||||
if (container) container.style.transform = 'none'
|
|
||||||
|
|
||||||
const canvas = await html2canvas(element, {
|
|
||||||
scale: 2,
|
|
||||||
useCORS: true,
|
|
||||||
allowTaint: true,
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
})
|
|
||||||
|
|
||||||
if (container) container.style.transform = prevTransform ?? ''
|
|
||||||
|
|
||||||
const imgData = canvas.toDataURL('image/png')
|
|
||||||
const imgWidth = 210
|
|
||||||
const imgHeight = 297
|
|
||||||
if (i > 0) pdf.addPage()
|
|
||||||
pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf.save(
|
|
||||||
`${report!.templateName}_${new Date(report!.creationTime).toLocaleDateString('tr-TR')}.pdf`,
|
|
||||||
)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF oluşturma hatası:', error)
|
|
||||||
alert('PDF oluşturulurken bir hata oluştu.')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-gray-50">
|
|
||||||
{/* Header - Print edilmeyecek */}
|
|
||||||
<div className="print:hidden bg-white shadow-sm border-b border-gray-200 sticky top-0 z-10">
|
|
||||||
<div className="w-full px-4">
|
|
||||||
<div className="flex items-center justify-between h-16">
|
|
||||||
<div className="flex items-center space-x-4 flex-1">
|
|
||||||
<div className="flex-1">
|
|
||||||
<h1 className="text-lg font-semibold text-gray-900">{report.templateName}</h1>
|
|
||||||
<div className="flex items-center space-x-4 text-sm text-gray-500">
|
|
||||||
<span className="flex items-center">
|
|
||||||
<FaCalendarAlt className="h-4 w-4 mr-1" />
|
|
||||||
{new Date(report.creationTime).toLocaleDateString('tr-TR', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
{template && (
|
|
||||||
<span className="flex items-center">
|
|
||||||
<FaFileAlt className="h-4 w-4 mr-1" />
|
|
||||||
{categories.find((c) => c.id === template.categoryId)?.name}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-2 flex-shrink-0">
|
|
||||||
<Button variant="solid" onClick={handleZoomOut} disabled={zoomLevel <= 50} size="sm">
|
|
||||||
<FaSearchMinus className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
<span className="text-sm text-gray-600 px-2 min-w-[4rem] text-center">
|
|
||||||
{zoomLevel}%
|
|
||||||
</span>
|
|
||||||
<Button variant="solid" onClick={handleZoomIn} disabled={zoomLevel >= 200} size="sm">
|
|
||||||
<FaSearchPlus className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
<div className="w-px h-6 bg-gray-300 mx-2"></div>
|
|
||||||
<Button
|
|
||||||
onMouseEnter={preloadPdfLibs} // ← opsiyonel prefetch
|
|
||||||
onClick={handleDownloadPdf}
|
|
||||||
className="bg-white-600 hover:bg-white-700 font-medium px-2 sm:px-3 py-1.5 rounded text-xs flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<FaDownload className="h-4 w-4 mr-2" />
|
|
||||||
{translate('::App.Reports.ReportViewer.DownloadPDF')}
|
|
||||||
</Button>
|
|
||||||
<Button variant="solid" onClick={handlePrint}>
|
|
||||||
{translate('::App.Reports.ReportViewer.Print')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Rapor İçeriği */}
|
|
||||||
<div className="flex justify-center bg-gray-200 py-8 print:bg-white print:py-0">
|
|
||||||
<div
|
|
||||||
className="space-y-8 print:space-y-0 transition-transform duration-300 ease-in-out"
|
|
||||||
style={{
|
|
||||||
transform: `scale(${zoomLevel / 100})`,
|
|
||||||
transformOrigin: 'top center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{memoizedPages.map((pageContent, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
id={index === 0 ? 'report-content' : `report-content-page-${index + 1}`}
|
|
||||||
className="bg-white shadow-lg print:shadow-none page-container"
|
|
||||||
style={{
|
|
||||||
width: '210mm',
|
|
||||||
minHeight: '297mm',
|
|
||||||
padding: '0',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
position: 'relative',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{index === 0 && (
|
|
||||||
<style>
|
|
||||||
{`
|
|
||||||
/* Sayfa kırılması için CSS */
|
|
||||||
.page-container {
|
|
||||||
page-break-after: always;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container:last-child {
|
|
||||||
page-break-after: auto;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Header ve Footer stilleri */
|
|
||||||
.page-header {
|
|
||||||
height: 15mm;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: right;
|
|
||||||
background-color: transparent;
|
|
||||||
color: #666;
|
|
||||||
font-size: 10px;
|
|
||||||
padding: 0 20mm;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer {
|
|
||||||
height: 15mm;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
background-color: transparent;
|
|
||||||
color: #666;
|
|
||||||
font-size: 10px;
|
|
||||||
padding: 0 20mm;
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin-top: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-content-area {
|
|
||||||
flex: 1;
|
|
||||||
padding: 0 20mm;
|
|
||||||
min-height: 267mm; /* 297mm - 15mm header - 15mm footer */
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* İçerik için sayfa kırılması kuralları */
|
|
||||||
.page-container h1, .page-container h2, .page-container h3 {
|
|
||||||
page-break-after: avoid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container table {
|
|
||||||
page-break-inside: avoid;
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container table td,
|
|
||||||
.page-container table th {
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
text-align: left;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print specific styles */
|
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container {
|
|
||||||
width: 210mm !important;
|
|
||||||
min-height: 297mm !important;
|
|
||||||
margin: 0 !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
page-break-after: always !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container:last-child {
|
|
||||||
page-break-after: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
height: 15mm !important;
|
|
||||||
color: #666 !important;
|
|
||||||
-webkit-print-color-adjust: exact !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-footer {
|
|
||||||
height: 15mm !important;
|
|
||||||
color: #666 !important;
|
|
||||||
-webkit-print-color-adjust: exact !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-content-area {
|
|
||||||
padding: 0 20mm !important;
|
|
||||||
min-height: 267mm !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.print\\:hidden {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Table print styles */
|
|
||||||
.page-container table {
|
|
||||||
border-collapse: collapse !important;
|
|
||||||
page-break-inside: avoid !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container table th,
|
|
||||||
.page-container table td {
|
|
||||||
border: 1px solid #000 !important;
|
|
||||||
page-break-inside: avoid !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container table th {
|
|
||||||
background-color: #f0f0f0 !important;
|
|
||||||
-webkit-print-color-adjust: exact !important;
|
|
||||||
color-adjust: exact !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-container table tr:nth-child(even) {
|
|
||||||
background-color: #f5f5f5 !important;
|
|
||||||
-webkit-print-color-adjust: exact !important;
|
|
||||||
color-adjust: exact !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
</style>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Sayfa Header - Tarih ve Saat */}
|
|
||||||
<div className="page-header">
|
|
||||||
{new Date().toLocaleDateString('tr-TR', {
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Sayfa İçeriği */}
|
|
||||||
<div className="page-content-area">
|
|
||||||
<div dangerouslySetInnerHTML={{ __html: pageContent }} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Sayfa Footer - Sayfa Numarası */}
|
|
||||||
<div className="page-footer">
|
|
||||||
{translate('::App.Reports.ReportViewer.Page')} {index + 1} / {memoizedPages.length}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import { Button } from '../ui/Button'
|
|
||||||
import { FaFileAlt, FaEdit, FaTrash, FaPlay } from 'react-icons/fa'
|
|
||||||
import { ReportCategoryDto, ReportTemplateDto } from '@/proxy/reports/models'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
|
|
||||||
interface TemplateCardProps {
|
|
||||||
template: ReportTemplateDto
|
|
||||||
categories: ReportCategoryDto[]
|
|
||||||
onEdit: (template: ReportTemplateDto) => void
|
|
||||||
onDelete: (id: string) => void
|
|
||||||
onGenerate: (template: ReportTemplateDto) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TemplateCard: React.FC<TemplateCardProps> = ({
|
|
||||||
template,
|
|
||||||
categories,
|
|
||||||
onEdit,
|
|
||||||
onDelete,
|
|
||||||
onGenerate,
|
|
||||||
}) => {
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="bg-white rounded-xl shadow-md hover:shadow-lg transition-all duration-200 border border-gray-200 flex flex-col">
|
|
||||||
<div className="p-4 flex-1 flex flex-col">
|
|
||||||
{/* Header with title and parameter count */}
|
|
||||||
<div className="flex items-start justify-between mb-3 min-h-0">
|
|
||||||
<div className="flex-1 min-w-0 pr-3">
|
|
||||||
<h3 className="text-lg font-semibold text-gray-900 mb-2 truncate">{template.name}</h3>
|
|
||||||
<p className="text-gray-600 text-sm mb-3 line-clamp-2">{template.description}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center gap-1 flex-shrink-0 bg-gray-50 px-2 py-1 rounded-lg">
|
|
||||||
<FaFileAlt className="h-4 w-4 text-blue-500" />
|
|
||||||
<span className="text-xs text-gray-500 whitespace-nowrap">
|
|
||||||
{template.parameters.length}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tags section with proper wrapping */}
|
|
||||||
<div className="flex items-center gap-1 mb-4 flex-wrap min-h-0">
|
|
||||||
<span className="text-xs bg-blue-100 text-blue-800 px-2 py-1 rounded-full font-medium flex-shrink-0">
|
|
||||||
{categories.find((c) => c.id === template.categoryId)?.name}
|
|
||||||
</span>
|
|
||||||
{template.tags.slice(0, 2).map((tag) => (
|
|
||||||
<span
|
|
||||||
key={tag}
|
|
||||||
className="text-xs bg-gray-100 text-gray-600 px-2 py-1 rounded-full flex-shrink-0 max-w-20 truncate"
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
{template.tags.length > 2 && (
|
|
||||||
<span className="text-xs text-gray-500 flex-shrink-0">+{template.tags.length - 2}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Footer with date and actions */}
|
|
||||||
<div className="flex flex-col gap-3 mt-auto pt-3 border-t border-gray-100">
|
|
||||||
<div className="text-xs text-gray-500">
|
|
||||||
<p className="truncate">
|
|
||||||
{new Date(template.lastModificationTime || template.creationTime).toLocaleString(
|
|
||||||
'tr-TR',
|
|
||||||
{
|
|
||||||
day: '2-digit',
|
|
||||||
month: '2-digit',
|
|
||||||
year: 'numeric',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-center gap-2 w-full">
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => onGenerate(template)}
|
|
||||||
className="bg-gray-600 hover:bg-gray-700 font-medium px-3 py-1.5 rounded text-xs flex items-center gap-1 flex-1 justify-center min-w-0"
|
|
||||||
>
|
|
||||||
<FaPlay className="h-3 w-3" />
|
|
||||||
<span className="truncate">{translate('::App.Reports.TemplateCard.Show')}</span>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant="default"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => onEdit(template)}
|
|
||||||
className="font-medium px-3 py-1.5 rounded text-xs flex items-center gap-1 flex-1 justify-center min-w-0"
|
|
||||||
>
|
|
||||||
<FaEdit className="h-3 w-3" />
|
|
||||||
<span className="truncate">{translate('::Abp.Identity.OrganizationUnit.Edit')}</span>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => onDelete(template.id)}
|
|
||||||
className="bg-red-600 hover:bg-red-700 font-medium px-3 py-1.5 rounded text-xs flex items-center justify-center flex-1 min-w-0"
|
|
||||||
>
|
|
||||||
<FaTrash className="h-3 w-3" />
|
|
||||||
<span className="truncate">{translate('::Delete')}</span>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,437 +0,0 @@
|
||||||
import React, { useState, useEffect } from 'react'
|
|
||||||
import { FaSave, FaTimes, FaFileAlt, FaCode, FaCog } from 'react-icons/fa'
|
|
||||||
import { ReportHtmlEditor } from './ReportHtmlEditor'
|
|
||||||
import { ReportParameterDto, ReportTemplateDto, ReportCategoryDto } from '@/proxy/reports/models'
|
|
||||||
import { Button, Input, Dialog } from '../ui'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
|
|
||||||
interface TemplateEditorProps {
|
|
||||||
isOpen: boolean
|
|
||||||
onClose: () => void
|
|
||||||
onSave: (template: ReportTemplateDto) => Promise<void>
|
|
||||||
template?: ReportTemplateDto | null
|
|
||||||
categories: ReportCategoryDto[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TemplateEditor: React.FC<TemplateEditorProps> = ({
|
|
||||||
isOpen,
|
|
||||||
onClose,
|
|
||||||
onSave,
|
|
||||||
template,
|
|
||||||
categories,
|
|
||||||
}) => {
|
|
||||||
const [activeTab, setActiveTab] = useState<'info' | 'parameters' | 'content'>('info')
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
htmlContent: '',
|
|
||||||
categoryId: '',
|
|
||||||
tags: [] as string[],
|
|
||||||
parameters: [] as ReportParameterDto[],
|
|
||||||
})
|
|
||||||
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
const [tagInput, setTagInput] = useState('')
|
|
||||||
const [isSaving, setIsSaving] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (template) {
|
|
||||||
setFormData({
|
|
||||||
name: template.name,
|
|
||||||
description: template.description || '',
|
|
||||||
htmlContent: template.htmlContent,
|
|
||||||
categoryId: template.categoryId!,
|
|
||||||
tags: template.tags,
|
|
||||||
parameters: template.parameters,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
setFormData({
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
htmlContent: '',
|
|
||||||
categoryId: '',
|
|
||||||
tags: [],
|
|
||||||
parameters: [],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
setActiveTab('info')
|
|
||||||
}, [template, isOpen])
|
|
||||||
|
|
||||||
// Otomatik parametre algılama
|
|
||||||
useEffect(() => {
|
|
||||||
const extractParameters = (htmlContent: string) => {
|
|
||||||
const paramRegex = /@@([\p{L}0-9_]+)/gu
|
|
||||||
const matches = [...htmlContent.matchAll(paramRegex)]
|
|
||||||
const uniqueParams = [...new Set(matches.map((match) => match[1]))]
|
|
||||||
|
|
||||||
const newParameters: ReportParameterDto[] = uniqueParams.map((paramName) => {
|
|
||||||
// Mevcut parametreyi kontrol et
|
|
||||||
const existingParam = formData.parameters.find((p) => p.name === paramName)
|
|
||||||
if (existingParam) {
|
|
||||||
return existingParam
|
|
||||||
}
|
|
||||||
|
|
||||||
// Yeni parametre oluştur
|
|
||||||
return {
|
|
||||||
id: crypto.randomUUID(),
|
|
||||||
templateId: template?.id || '',
|
|
||||||
name: paramName,
|
|
||||||
placeholder: `@@${paramName}`,
|
|
||||||
type: 'text',
|
|
||||||
required: true,
|
|
||||||
description: `${paramName} parametresi`,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
parameters: newParameters,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (formData.htmlContent) {
|
|
||||||
extractParameters(formData.htmlContent)
|
|
||||||
}
|
|
||||||
}, [formData.htmlContent])
|
|
||||||
|
|
||||||
const handleSave = async () => {
|
|
||||||
if (!formData.name.trim() || !formData.htmlContent.trim()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('FormData before save:', formData)
|
|
||||||
console.log('Categories available:', categories)
|
|
||||||
|
|
||||||
setIsSaving(true)
|
|
||||||
try {
|
|
||||||
await onSave(formData as unknown as ReportTemplateDto)
|
|
||||||
onClose()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error saving template:', error)
|
|
||||||
// Handle error - could show toast notification
|
|
||||||
} finally {
|
|
||||||
setIsSaving(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const addTag = () => {
|
|
||||||
if (tagInput.trim() && !formData.tags.includes(tagInput.trim())) {
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
tags: [...prev.tags, tagInput.trim()],
|
|
||||||
}))
|
|
||||||
setTagInput('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeTag = (tagToRemove: string) => {
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
tags: prev.tags.filter((tag) => tag !== tagToRemove),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateParameter = (paramId: string, updates: Partial<ReportParameterDto>) => {
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
parameters: prev.parameters.map((param) =>
|
|
||||||
param.id === paramId ? { ...param, ...updates } : param,
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabs = [
|
|
||||||
{ id: 'info', label: translate('::App.Reports.TemplateEditor.Tab.Info'), icon: FaFileAlt },
|
|
||||||
{
|
|
||||||
id: 'parameters',
|
|
||||||
label: translate('::App.Reports.TemplateEditor.Tab.Parameters'),
|
|
||||||
icon: FaCog,
|
|
||||||
},
|
|
||||||
{ id: 'content', label: translate('::App.Reports.TemplateEditor.Tab.Content'), icon: FaCode },
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Dialog isOpen={isOpen} onClose={onClose} width="100%">
|
|
||||||
<h5 className="mb-4">
|
|
||||||
{template
|
|
||||||
? translate('::App.Reports.TemplateEditor.TitleEdit')
|
|
||||||
: translate('::App.Reports.TemplateEditor.TitleNew')}
|
|
||||||
</h5>
|
|
||||||
<div className="flex flex-col h-full">
|
|
||||||
{/* Tab Navigation */}
|
|
||||||
<div className="border-b border-gray-200 bg-gray-50 flex-shrink-0">
|
|
||||||
<nav className="flex space-x-8 px-6">
|
|
||||||
{tabs.map((tab) => {
|
|
||||||
const Icon = tab.icon
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
key={tab.id}
|
|
||||||
onClick={() => setActiveTab(tab.id as 'info' | 'content' | 'parameters')}
|
|
||||||
className={`
|
|
||||||
flex items-center py-4 px-1 border-b-2 font-medium text-sm transition-colors
|
|
||||||
${
|
|
||||||
activeTab === tab.id
|
|
||||||
? 'border-blue-500 text-blue-600'
|
|
||||||
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<Icon className="h-4 w-4 mr-2" />
|
|
||||||
{tab.label}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tab Content */}
|
|
||||||
<div className="flex-1 flex flex-col min-h-0">
|
|
||||||
{activeTab === 'info' && (
|
|
||||||
<div className="overflow-y-auto flex-1 p-3">
|
|
||||||
<div className="mx-auto">
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
||||||
{/* Left Column - Basic Info */}
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
||||||
{translate('::App.Reports.TemplateEditor.Label.Name')}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
autoFocus
|
|
||||||
value={formData.name}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
name: e.target.value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
placeholder={translate('::App.Reports.TemplateEditor.Placeholder.Name')}
|
|
||||||
className="w-full flex-1 px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
||||||
{translate('::App.Reports.TemplateEditor.Label.Category')}
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
value={formData.categoryId}
|
|
||||||
onChange={(e) => {
|
|
||||||
console.log('Category selected:', e.target.value)
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
categoryId: e.target.value,
|
|
||||||
}))
|
|
||||||
}}
|
|
||||||
className="block w-full px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
>
|
|
||||||
<option value="">
|
|
||||||
{translate('::App.Reports.TemplateEditor.Placeholder.SelectCategory')}
|
|
||||||
</option>
|
|
||||||
{categories.map((category) => (
|
|
||||||
<option key={category.id} value={category.id}>
|
|
||||||
{category.name}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
||||||
{translate('::App.Reports.TemplateEditor.Label.Tags')}
|
|
||||||
</label>
|
|
||||||
<div className="flex space-x-2 mb-3">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={tagInput}
|
|
||||||
onChange={(e) => setTagInput(e.target.value)}
|
|
||||||
onKeyPress={(e) => e.key === 'Enter' && addTag()}
|
|
||||||
placeholder={translate(
|
|
||||||
'::App.Reports.TemplateEditor.Placeholder.AddTag',
|
|
||||||
)}
|
|
||||||
className="flex-1 px-3 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
/>
|
|
||||||
<Button type="button" onClick={addTag} size="sm">
|
|
||||||
{translate('::App.Reports.TemplateEditor.Button.Add')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap gap-2">
|
|
||||||
{formData.tags.map((tag) => (
|
|
||||||
<span
|
|
||||||
key={tag}
|
|
||||||
className="inline-flex items-center px-3 py-1 text-sm bg-blue-100 text-blue-800 rounded-full"
|
|
||||||
>
|
|
||||||
{tag}
|
|
||||||
<button
|
|
||||||
onClick={() => removeTag(tag)}
|
|
||||||
className="ml-2 text-blue-600 hover:text-blue-800"
|
|
||||||
>
|
|
||||||
<FaTimes className="h-3 w-3" />
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right Column - Description */}
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div>
|
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
|
||||||
{translate('::App.Reports.TemplateEditor.Label.Description')}
|
|
||||||
</label>
|
|
||||||
<Input
|
|
||||||
value={formData.description}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
description: e.target.value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
placeholder={translate(
|
|
||||||
'::App.Reports.TemplateEditor.Placeholder.Description',
|
|
||||||
)}
|
|
||||||
textArea={true}
|
|
||||||
rows={12}
|
|
||||||
className="text-left h-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{activeTab === 'content' && (
|
|
||||||
<div className="flex-1 flex flex-col min-h-0">
|
|
||||||
<div className="flex-1 p-3 min-h-0">
|
|
||||||
<ReportHtmlEditor
|
|
||||||
value={formData.htmlContent}
|
|
||||||
onChange={(content) =>
|
|
||||||
setFormData((prev) => ({ ...prev, htmlContent: content }))
|
|
||||||
}
|
|
||||||
height="50vh"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{activeTab === 'parameters' && (
|
|
||||||
<div className="overflow-y-auto flex-1 p-6">
|
|
||||||
<div className="max-w-full mx-auto">
|
|
||||||
{formData.parameters.length === 0 ? (
|
|
||||||
<div className="text-center py-12">
|
|
||||||
<FaCog className="h-16 w-16 text-gray-400 mx-auto mb-4" />
|
|
||||||
<p className="text-gray-500 text-lg mb-2">
|
|
||||||
{translate('::App.Reports.TemplateEditor.NoParameters')}
|
|
||||||
</p>
|
|
||||||
<p className="text-gray-400 text-sm">
|
|
||||||
{translate('::App.Reports.TemplateEditor.NoParametersDescription')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
|
|
||||||
{formData.parameters.map((param) => (
|
|
||||||
<div
|
|
||||||
key={param.id}
|
|
||||||
className="bg-white p-3 rounded-lg border border-gray-200 shadow-sm hover:shadow-md transition-shadow min-w-0"
|
|
||||||
>
|
|
||||||
<div className="flex items-start justify-between mb-2 min-w-0">
|
|
||||||
<div className="flex items-center gap-1 min-w-0 flex-1">
|
|
||||||
<div className="w-2 h-2 bg-blue-500 rounded-full flex-shrink-0"></div>
|
|
||||||
<code className="text-xs font-mono text-blue-700 bg-blue-50 px-1.5 py-0.5 rounded truncate">
|
|
||||||
@@{param.name}
|
|
||||||
</code>
|
|
||||||
</div>
|
|
||||||
<select
|
|
||||||
value={param.type}
|
|
||||||
onChange={(e) =>
|
|
||||||
updateParameter(param.id, { type: e.target.value as any })
|
|
||||||
}
|
|
||||||
className="text-xs bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded-full flex-shrink-0 ml-1 border-none outline-none cursor-pointer"
|
|
||||||
>
|
|
||||||
<option value="text">text</option>
|
|
||||||
<option value="number">number</option>
|
|
||||||
<option value="date">date</option>
|
|
||||||
<option value="select">select</option>
|
|
||||||
<option value="checkbox">checkbox</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={param.description || ''}
|
|
||||||
onChange={(e) =>
|
|
||||||
updateParameter(param.id, { description: e.target.value })
|
|
||||||
}
|
|
||||||
placeholder={translate(
|
|
||||||
'::App.Reports.TemplateEditor.Placeholder.ParameterDescription',
|
|
||||||
)}
|
|
||||||
className="w-full text-xs text-gray-600 bg-transparent border-none outline-none resize-none"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={param.defaultValue || ''}
|
|
||||||
onChange={(e) =>
|
|
||||||
updateParameter(param.id, { defaultValue: e.target.value })
|
|
||||||
}
|
|
||||||
placeholder={translate(
|
|
||||||
'::ListForms.ListFormEdit.ExtraDefaultValue',
|
|
||||||
)}
|
|
||||||
className="w-full text-xs bg-gray-50 px-1.5 py-0.5 rounded border border-gray-200 outline-none"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<label className="flex items-center gap-1 cursor-pointer">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={param.required}
|
|
||||||
onChange={(e) =>
|
|
||||||
updateParameter(param.id, { required: e.target.checked })
|
|
||||||
}
|
|
||||||
className="w-3 h-3 text-red-600 rounded border-gray-300 focus:ring-red-500"
|
|
||||||
/>
|
|
||||||
<span className="text-xs text-gray-600">
|
|
||||||
{translate('::App.Required')}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tab Footer */}
|
|
||||||
<div className="flex justify-between">
|
|
||||||
<Button variant="default" onClick={onClose} disabled={isSaving}>
|
|
||||||
{translate('::Cancel')}
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
onClick={handleSave}
|
|
||||||
className="bg-blue-600 hover:bg-blue-700 font-medium px-2 py-2 rounded-lg shadow-md hover:shadow-lg transition-all duration-200 flex items-center space-x-2"
|
|
||||||
>
|
|
||||||
<FaSave className="h-5 w-5" />
|
|
||||||
{isSaving
|
|
||||||
? translate('::App.Reports.TemplateEditor.Button.Saving')
|
|
||||||
: template
|
|
||||||
? translate('::Update')
|
|
||||||
: translate('::App.Reports.TemplateEditor.Button.Save')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Dialog>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
import { Helmet } from 'react-helmet'
|
|
||||||
import { Dashboard } from '@/components/reports/Dashboard'
|
|
||||||
import { Container } from '@/components/shared'
|
|
||||||
|
|
||||||
const DashboardPage: React.FC = () => {
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<Helmet
|
|
||||||
titleTemplate="%s | Erp Platform"
|
|
||||||
title={translate('::' + 'App.Reports')}
|
|
||||||
defaultTitle="Erp Platform"
|
|
||||||
></Helmet>
|
|
||||||
<Dashboard />
|
|
||||||
</Container>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DashboardPage
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import { ReportViewer } from '@/components/reports/ReportViewer'
|
|
||||||
import { Container } from '@/components/shared'
|
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
||||||
import React from 'react'
|
|
||||||
import { Helmet } from 'react-helmet'
|
|
||||||
|
|
||||||
const ReportViewerPage: React.FC = () => {
|
|
||||||
const { translate } = useLocalization()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<Helmet
|
|
||||||
titleTemplate="%s | Erp Platform"
|
|
||||||
title={translate('::' + 'App.Reports')}
|
|
||||||
defaultTitle="Erp Platform"
|
|
||||||
></Helmet>
|
|
||||||
<ReportViewer />
|
|
||||||
</Container>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ReportViewerPage
|
|
||||||
Loading…
Reference in a new issue