merge: feat/signFlow-gen in Master zusammenführen

This commit is contained in:
Developer 02 2024-09-20 11:16:08 +02:00
commit 662faf2512
117 changed files with 1436 additions and 461 deletions

View File

@ -5,7 +5,7 @@ using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IConfigService : IBasicCRUDService<ConfigDto, Config, int>
public interface IConfigService : IReadService<ConfigDto, Config, int>
{
Task<DataResult<ConfigDto>> ReadFirstAsync();

View File

@ -3,7 +3,6 @@ using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.Contracts

View File

@ -1,6 +1,6 @@
using DigitalData.Core.DTO;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Common;
namespace EnvelopeGenerator.Application.Contracts

View File

@ -1,15 +1,18 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, object>
public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>
{
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false);
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true);
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true);
Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true);
@ -25,5 +28,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<DataResult<bool>> IsExisting(string envelopeReceiverId);
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail);
}
}

View File

@ -2,7 +2,6 @@
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Contracts
{
@ -11,5 +10,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false);
Task<DataResult<EnvelopeDto>> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false);
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[]ignore_statuses);
}
}

View File

@ -1,7 +1,6 @@
using DigitalData.Core.Abstractions.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Contracts
{

View File

@ -1,4 +1,7 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs
{
public record ConfigDto(
string DocumentPath,
@ -8,5 +11,10 @@
string ExportPath,
string DocumentPathDmz,
string ExportPathDmz,
string DocumentPathMoveAftsend);
string DocumentPathMoveAftsend) : IUnique<int>
{
[JsonIgnore]
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single row in the database.");
};
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record DocumentReceiverElementDto(
int Id,
@ -18,5 +20,5 @@
DateTime? ChangedWhen,
double Top,
double Left
);
): IUnique<int>;
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record DocumentStatusDto(
int Id,
@ -8,5 +10,5 @@
DateTime? StatusChangedWhen,
string Value,
DateTime AddedWhen,
DateTime? ChangedWhen);
DateTime? ChangedWhen) : IUnique<int>;
}

View File

@ -1,8 +1,10 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record EmailTemplateDto(
int Id,
string Name,
string Body,
string Subject);
string Subject) : IUnique<int>;
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeCertificateDto(
int Id,
@ -8,5 +10,5 @@
int CreatorId,
string CreatorName,
string CreatorEmail,
int EnvelopeStatus);
int EnvelopeStatus) : IUnique<int>;
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeDocumentDto
(
@ -6,5 +8,5 @@
int EnvelopeId,
DateTime AddedWhen,
IEnumerable<DocumentReceiverElementDto>? Elements
);
) : IUnique<int>;
}

View File

@ -1,10 +1,11 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeDto()
public record EnvelopeDto() : IUnique<int>
{
public int Id { get; set; }

View File

@ -1,4 +1,5 @@
using DigitalData.Core.DTO;
using DigitalData.Core.Abstractions;
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Application.DTOs.Receiver;
using static EnvelopeGenerator.Common.Constants;
@ -10,10 +11,11 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
int EnvelopeId,
string UserReference,
int Status,
string? StatusName,
DateTime AddedWhen,
DateTime? ActionDate,
UserCreateDto? Sender,
ReceiverReadDto? Receiver,
ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id);
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
}

View File

@ -0,0 +1,29 @@
using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
public record EnvelopeReceiverBasicDto() : IUnique<(int Envelope, int Receiver)>
{
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
public int EnvelopeId { get; init; }
public int ReceiverId { get; init; }
public int Sequence { get; init; }
[TemplatePlaceholder("[NAME_RECEIVER]")]
public string? Name { get; init; }
public string? JobTitle { get; init; }
public string? CompanyName { get; init; }
public string? PrivateMessage { get; init; }
public DateTime AddedWhen { get; init; }
public DateTime? ChangedWhen { get; init; }
}
}

View File

@ -0,0 +1,11 @@
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
{
public EnvelopeDto? Envelope { get; set; }
public ReceiverReadDto? Receiver { get; set; }
}
}

View File

@ -0,0 +1,4 @@
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
public record EnvelopeReceiverSecretDto(string? AccessCode) : EnvelopeReceiverDto;
}

View File

@ -1,31 +0,0 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeReceiverDto()
{
public int EnvelopeId { get; set; }
public int ReceiverId { get; set; }
public int Sequence { get; set; }
[TemplatePlaceholder("[NAME_RECEIVER]")]
public string? Name { get; set; }
public string? JobTitle { get; set; }
public string? CompanyName { get; set; }
public string? PrivateMessage { get; set; }
public DateTime AddedWhen { get; set; }
public DateTime? ChangedWhen { get; set; }
public EnvelopeDto? Envelope { get; set; }
public ReceiverReadDto? Receiver { get; set; }
}
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeTypeDto(
int Id,
@ -15,5 +17,5 @@
bool? SendReminderEmails,
int? FirstReminderDays,
int? ReminderIntervalDays,
int? ContractType);
int? ContractType) : IUnique<int>;
}

View File

@ -1,4 +1,6 @@
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
@ -6,6 +8,12 @@ namespace EnvelopeGenerator.Application.DTOs.Receiver
int Id,
string EmailAddress,
string Signature,
DateTime AddedWhen
) : BaseDTO<int>(Id);
DateTime AddedWhen
) : BaseDTO<int>(Id)
{
[JsonIgnore]
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; init; }
public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name;
};
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs.Receiver
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverUpdateDto();
public record ReceiverUpdateDto(int Id) : IUnique<int>;
}

View File

@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{
public record UserReceiverDto(
int Id,
@ -7,5 +9,5 @@
string Name,
string CompanyName,
string JobTitle,
DateTime AddedWhen);
DateTime AddedWhen) : IUnique<int>;
}

View File

@ -12,13 +12,13 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" />
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="1.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="2.0.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
<PackageReference Include="UserManager.Application" Version="1.0.0" />
<PackageReference Include="UserManager.Infrastructure" Version="1.0.0" />
<PackageReference Include="UserManager.Application" Version="2.0.0" />
<PackageReference Include="UserManager.Infrastructure" Version="2.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -1,6 +1,7 @@
using AutoMapper;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
@ -21,6 +22,7 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<EnvelopeHistory, EnvelopeHistoryDto>();
CreateMap<EnvelopeHistory, EnvelopeHistoryCreateDto>();
CreateMap<EnvelopeReceiver, EnvelopeReceiverDto>();
CreateMap<EnvelopeReceiver, EnvelopeReceiverSecretDto>();
CreateMap<EnvelopeType, EnvelopeTypeDto>();
CreateMap<Receiver, ReceiverReadDto>();
CreateMap<Receiver, ReceiverCreateDto>();
@ -43,6 +45,7 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<ReceiverCreateDto, Receiver>();
CreateMap<ReceiverUpdateDto, Receiver>();
CreateMap<UserReceiverDto, UserReceiver>();
CreateMap<EnvelopeReceiverBase, EnvelopeReceiverBasicDto>();
}
}
}

View File

@ -3,15 +3,13 @@ using DigitalData.Core.Application;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services
{
public class ConfigService : BasicCRUDService<IConfigRepository, ConfigDto, Config, int>, IConfigService
public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, int>, IConfigService
{
private static readonly Guid DefaultConfigCacheId = Guid.NewGuid();
@ -28,7 +26,7 @@ namespace EnvelopeGenerator.Application.Services
var config = await _repository.ReadFirstAsync();
return config is null
? Result.Fail<ConfigDto>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, "There is no configuration in DB.")
: Result.Success(_mapper.MapOrThrow<ConfigDto>(config));
: Result.Success(_mapper.Map<ConfigDto>(config));
}
/// <summary>

View File

@ -2,10 +2,8 @@
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
namespace EnvelopeGenerator.Application.Services
{

View File

@ -2,10 +2,8 @@
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
namespace EnvelopeGenerator.Application.Services
{

View File

@ -1,11 +1,9 @@
using AutoMapper;
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using static EnvelopeGenerator.Common.Constants;
using DigitalData.Core.DTO;
using Microsoft.Extensions.Logging;
@ -26,7 +24,7 @@ namespace EnvelopeGenerator.Application.Services
? Result.Fail<EmailTemplateDto>()
.Message(Key.InnerServiceError)
.Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"EmailTemplateType '{type}' is not found in DB. Please, define required e-mail template.")
: Result.Success(_mapper.MapOrThrow<EmailTemplateDto>(temp));
: Result.Success(_mapper.Map<EmailTemplateDto>(temp));
}
}
}

View File

@ -1,11 +1,9 @@
using AutoMapper;
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Application.Resources;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
@ -14,7 +12,7 @@ namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistoryDto, EnvelopeHistory, long>, IEnvelopeHistoryService
{
public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
@ -53,7 +51,7 @@ namespace EnvelopeGenerator.Application.Services
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false)
{
var histDTOs = _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>(
var histDTOs = _mapper.Map<IEnumerable<EnvelopeHistoryDto>>(
await _repository.ReadAsync(
envelopeId: envelopeId,
userReference: userReference,

View File

@ -5,7 +5,7 @@ using DigitalData.EmailProfilerDispatcher.Abstraction.DTOs.EmailOut;
using DigitalData.EmailProfilerDispatcher.Abstraction.Services;
using DigitalData.UserManager.Application;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Common;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
@ -14,7 +14,7 @@ using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
{
private readonly IEmailTemplateService _tempService;
private readonly IEnvelopeReceiverService _envRcvService;

View File

@ -2,7 +2,7 @@
using DigitalData.Core.Application;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, object>, IEnvelopeReceiverService
public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>, IEnvelopeReceiverService
{
private readonly IStringLocalizer<Resource> _localizer;
@ -24,13 +24,19 @@ namespace EnvelopeGenerator.Application.Services
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true)
{
var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(_mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
}
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false)
{
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(_mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
}
public async Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true)
{
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverSecretDto>>(env_rcvs));
}
public async Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true)
@ -40,7 +46,7 @@ namespace EnvelopeGenerator.Application.Services
return Result.Fail<EnvelopeReceiverDto>()
.Message(Key.EnvelopeReceiverNotFound);
return Result.Success(_mapper.MapOrThrow<EnvelopeReceiverDto>(env_rcv));
return Result.Success(_mapper.Map<EnvelopeReceiverDto>(env_rcv));
}
public async Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true)
@ -119,8 +125,14 @@ namespace EnvelopeGenerator.Application.Services
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
{
var er_list = await _repository.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
var dto_list = _mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(er_list);
var dto_list = _mapper.Map<IEnumerable<EnvelopeReceiverDto>>(er_list);
return Result.Success(dto_list);
}
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail)
{
var er = await _repository.ReadLastByReceiver(mail);
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
}
}
}

View File

@ -3,27 +3,22 @@ using DigitalData.Core.Application;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto, Envelope, int>, IEnvelopeService
{
private readonly ILogger _logger;
public EnvelopeService(IEnvelopeRepository repository, IMapper mapper, ILogger<EnvelopeService> logger)
public EnvelopeService(IEnvelopeRepository repository, IMapper mapper)
: base(repository, mapper)
{
_logger = logger;
}
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false)
{
var envelopes = await _repository.ReadAllWithAsync(documents: documents, history: history, documentReceiverElement: documentReceiverElement);
var readDto = _mapper.MapOrThrow<IEnumerable<EnvelopeDto>>(envelopes);
var readDto = _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
return Result.Success(readDto);
}
@ -34,7 +29,14 @@ namespace EnvelopeGenerator.Application.Services
if (envelope is null)
return Result.Fail<EnvelopeDto>();
var readDto = _mapper.MapOrThrow<EnvelopeDto>(envelope);
var readDto = _mapper.Map<EnvelopeDto>(envelope);
return Result.Success(readDto);
}
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
{
var users = await _repository.ReadByUserAsync(userId: userId, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
var readDto = _mapper.Map<IEnumerable<EnvelopeDto>>(users);
return Result.Success(readDto);
}
}

View File

@ -1,19 +1,30 @@
using AutoMapper;
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using Microsoft.Extensions.Caching.Memory;
using DigitalData.Core.DTO;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeTypeService : BasicCRUDService<IEnvelopeTypeRepository, EnvelopeTypeDto, EnvelopeType, int>, IEnvelopeTypeService
{
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper)
private static readonly Guid CacheKey = Guid.NewGuid();
private readonly IMemoryCache _cache;
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper, IMemoryCache cache)
: base(repository, mapper)
{
_cache = cache;
}
public override async Task<DataResult<IEnumerable<EnvelopeTypeDto>>> ReadAllAsync()
=> await _cache.GetOrCreateAsync(CacheKey, async entry => await base.ReadAllAsync())
?? Result.Fail<IEnumerable<EnvelopeTypeDto>>().Notice(LogLevel.Error, Flag.NotFound, "No cached envelope types are available in the database. If you have added any envelope types after the server started, please restart the server.");
}
}

View File

@ -1,10 +1,8 @@
using AutoMapper;
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Application.DTOs.Receiver;
using DigitalData.Core.DTO;
@ -12,7 +10,7 @@ namespace EnvelopeGenerator.Application.Services
{
public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>, IReceiverService
{
public ReceiverService(IReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
public ReceiverService(IReceiverRepository repository, IMapper mapper)
: base(repository, mapper)
{
}
@ -24,7 +22,7 @@ namespace EnvelopeGenerator.Application.Services
if (rcv is null)
return Result.Fail<ReceiverReadDto>();
return Result.Success(_mapper.MapOrThrow<ReceiverReadDto>(rcv));
return Result.Success(_mapper.Map<ReceiverReadDto>(rcv));
}
public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null)

View File

@ -1,17 +1,15 @@
using AutoMapper;
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
namespace EnvelopeGenerator.Application.Services
{
public class UserReceiverService : BasicCRUDService<IUserReceiverRepository, UserReceiverDto, UserReceiver, int>, IUserReceiverService
{
public UserReceiverService(IUserReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
public UserReceiverService(IUserReceiverRepository repository, IMapper mapper)
: base(repository, mapper)
{
}

View File

@ -26,6 +26,7 @@
MessageCompletionSent = 3005
End Enum
'TODO: standardize in xwiki
Public Enum ReferenceType
Receiver
Sender

View File

@ -1,43 +1,41 @@
using System.ComponentModel;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_CONFIG", Schema = "dbo")]
public class Config
public class Config : IUnique<int>
{
[Column("DOCUMENT_PATH", TypeName = "nvarchar(256)")]
public string DocumentPath { get; set; }
public string? DocumentPath { get; init; }
[Column("SENDING_PROFILE", TypeName = "int")]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)] // Assuming SENDING_PROFILE is manually entered or controlled by the application logic
[DefaultValue(0)] // This sets the default value for SENDING_PROFILE
public int SendingProfile { get; set; }
public required int SendingProfile { get; init; }
[Column("SIGNATURE_HOST", TypeName = "nvarchar(128)")]
public string SignatureHost { get; set; }
public string? SignatureHost { get; init; }
[Column("EXTERNAL_PROGRAM_NAME", TypeName = "nvarchar(30)")]
public string ExternalProgramName { get; set; }
public string? ExternalProgramName { get; init; }
[Column("EXPORT_PATH", TypeName = "nvarchar(256)")]
public string ExportPath { get; set; }
public string? ExportPath { get; init; }
[Column("DOCUMENT_PATH_DMZ", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_DMZ
public string DocumentPathDmz { get; set; }
public string? DocumentPathDmz { get; init; }
[Column("EXPORT_PATH_DMZ", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for EXPORT_PATH_DMZ
public string ExportPathDmz { get; set; }
public required string ExportPathDmz { get; init; }
[Column("DOCUMENT_PATH_MOVE_AFTSEND", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_MOVE_AFTSEND
public string DocumentPathMoveAftsend { get; set; }
public required string DocumentPathMoveAftsend { get; init; }
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single table in the database.");
}
}

View File

@ -1,11 +1,12 @@
using System.ComponentModel;
using DigitalData.Core.Abstractions;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_DOCUMENT_RECEIVER_ELEMENT", Schema = "dbo")]
public class DocumentReceiverElement
public class DocumentReceiverElement : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

View File

@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_DOCUMENT_STATUS", Schema = "dbo")]
public class DocumentStatus
public class DocumentStatus : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -27,7 +28,7 @@ namespace EnvelopeGenerator.Domain.Entities
public DateTime? StatusChangedWhen { get; set; }
[Column("VALUE", TypeName = "nvarchar(max)")]
public string Value { get; set; }
public string? Value { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
@ -42,4 +43,4 @@ namespace EnvelopeGenerator.Domain.Entities
[ForeignKey("ReceiverId")]
public virtual Receiver? Receiver { get; set; }
}
}
}

View File

@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_EMAIL_TEMPLATE", Schema = "dbo")]
public class EmailTemplate
public class EmailTemplate : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -12,12 +13,12 @@ namespace EnvelopeGenerator.Domain.Entities
public int Id { get; set; }
[Column("NAME", TypeName = "nvarchar(64)")]
public string Name { get; set; }
public string? Name { get; set; }
[Column("BODY", TypeName = "nvarchar(max)")]
public string Body { get; set; }
public string? Body { get; set; }
[Column("SUBJECT", TypeName = "nvarchar(512)")]
public string Subject { get; set; }
public string? Subject { get; set; }
}
}

View File

@ -1,12 +1,12 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Common.My.Resources;
using DigitalData.Core.Abstractions;
using EnvelopeGenerator.Common;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE", Schema = "dbo")]
public class Envelope
public class Envelope : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -26,11 +26,11 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
public string Uuid { get; set; }
public required string Uuid { get; init; }
[Required]
[Column("MESSAGE", TypeName = "nvarchar(max)")]
public string Message { get; set; }
public string? Message { get; set; }
[Column("EXPIRES_WHEN", TypeName = "datetime")]
public DateTime? ExpiresWhen { get; set; }
@ -46,13 +46,13 @@ namespace EnvelopeGenerator.Domain.Entities
public DateTime? ChangedWhen { get; set; }
[Column("TITLE", TypeName = "nvarchar(128)")]
public string Title { get; set; }
public string? Title { get; set; }
[Column("CONTRACT_TYPE")]
public int? ContractType { get; set; }
[Column("LANGUAGE", TypeName = "nvarchar(5)")]
public string Language { get; set; }
public required string Language { get; set; }
[Column("SEND_REMINDER_EMAILS")]
public bool? SendReminderEmails { get; set; }

View File

@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_CERTIFICATE", Schema = "dbo")]
public class EnvelopeCertificate
public class EnvelopeCertificate : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -17,11 +18,11 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
public string EnvelopeUuid { get; set; }
public required string EnvelopeUuid { get; set; }
[Required]
[Column("ENVELOPE_SUBJECT", TypeName = "nvarchar(512)")]
public string EnvelopeSubject { get; set; }
public required string EnvelopeSubject { get; set; }
[Required]
[Column("CREATOR_ID")]
@ -29,11 +30,11 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("CREATOR_NAME", TypeName = "nvarchar(128)")]
public string CreatorName { get; set; }
public required string CreatorName { get; set; }
[Required]
[Column("CREATOR_EMAIL", TypeName = "nvarchar(128)")]
public string CreatorEmail { get; set; }
public required string CreatorEmail { get; set; }
[Required]
[Column("ENVELOPE_STATUS")]

View File

@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_DOCUMENT", Schema = "dbo")]
public class EnvelopeDocument
public class EnvelopeDocument : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -17,18 +18,18 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("FILENAME", TypeName = "nvarchar(256)")]
public string Filename { get; set; }
public required string Filename { get; set; }
[Required]
[Column("FILEPATH", TypeName = "nvarchar(256)")]
public string Filepath { get; set; }
public required string Filepath { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
public required DateTime AddedWhen { get; set; }
[Column("FILENAME_ORIGINAL", TypeName = "nvarchar(256)")]
public string FilenameOriginal { get; set; }
public required string FilenameOriginal { get; set; }
public IEnumerable<DocumentReceiverElement>? Elements { get; set; }
}

View File

@ -1,4 +1,5 @@
using DigitalData.UserManager.Domain.Entities;
using DigitalData.Core.Abstractions;
using DigitalData.UserManager.Domain.Entities;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using static EnvelopeGenerator.Common.Constants;
@ -6,7 +7,7 @@ using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_HISTORY", Schema = "dbo")]
public class EnvelopeHistory
public class EnvelopeHistory : IUnique<long>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -19,7 +20,7 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("USER_REFERENCE", TypeName = "nvarchar(128)")]
public string UserReference { get; set; }
public required string UserReference { get; init; }
[Required]
[Column("STATUS")]
@ -43,11 +44,17 @@ namespace EnvelopeGenerator.Domain.Entities
public virtual Receiver? Receiver { get; set; }
[NotMapped]
public ReferenceType ReferenceType => (Status / 3) switch
public ReferenceType ReferenceType => (Status / 1000) switch
{
1 => ReferenceType.Sender,
2 or 3 => ReferenceType.Receiver,
_ => ReferenceType.Unknown,
};
[NotMapped]
public string? StatusName
=> (Enum.IsDefined(typeof(EnvelopeStatus), Status))
? Enum.GetName(typeof(EnvelopeStatus), Status)
: null;
}
}

View File

@ -1,45 +1,10 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")]
public class EnvelopeReceiver
public class EnvelopeReceiver : EnvelopeReceiverBase
{
[Key]
[Column("ENVELOPE_ID")]
public int EnvelopeId { get; set; }
[Key]
[Column("RECEIVER_ID")]
public int ReceiverId { get; set; }
[Required]
[Column("SEQUENCE")]
public int Sequence { get; set; }
[Column("NAME", TypeName = "nvarchar(128)")]
public string? Name { get; set; }
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
public string? JobTitle { get; set; }
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
public string? CompanyName { get; set; }
[Column("PRIVATE_MESSAGE", TypeName = "nvarchar(max)")]
public string? PrivateMessage { get; set; }
[Column("ACCESS_CODE", TypeName = "nvarchar(64)")]
public string? AccessCode { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
[Column("CHANGED_WHEN", TypeName = "datetime")]
public DateTime? ChangedWhen { get; set; }
[ForeignKey("EnvelopeId")]
public Envelope? Envelope { get; set; }

View File

@ -0,0 +1,46 @@
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")]
public class EnvelopeReceiverBase : IUnique<(int Envelope, int Receiver)>
{
[Key]
[Column("ENVELOPE_ID")]
public int EnvelopeId { get; set; }
[Key]
[Column("RECEIVER_ID")]
public int ReceiverId { get; set; }
[Required]
[Column("SEQUENCE")]
public int Sequence { get; set; }
[Column("NAME", TypeName = "nvarchar(128)")]
public string? Name { get; set; }
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
public string? JobTitle { get; set; }
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
public string? CompanyName { get; set; }
[Column("PRIVATE_MESSAGE", TypeName = "nvarchar(max)")]
public string? PrivateMessage { get; set; }
[Column("ACCESS_CODE", TypeName = "nvarchar(64)")]
public string? AccessCode { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
[Column("CHANGED_WHEN", TypeName = "datetime")]
public DateTime? ChangedWhen { get; set; }
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
}
}

View File

@ -1,12 +1,11 @@
using System;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_TYPE", Schema = "dbo")]
public class EnvelopeType
public class EnvelopeType : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -15,10 +14,10 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("TITLE", TypeName = "nvarchar(128)")]
public string Title { get; set; }
public required string Title { get; set; }
[Column("LANGUAGE", TypeName = "nvarchar(5)")]
public string Language { get; set; }
public string? Language { get; set; }
[Column("EXPIRES_DAYS")]
public int? ExpiresDays { get; set; }

View File

@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_RECEIVER", Schema = "dbo")]
public class Receiver
public class Receiver : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -22,5 +23,7 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
public IEnumerable<EnvelopeReceiver>? EnvelopeReceivers { get; init; }
}
}

View File

@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_USER_RECEIVER", Schema = "dbo")]
public class UserReceiver
public class UserReceiver : IUnique<int>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@ -21,16 +22,16 @@ namespace EnvelopeGenerator.Domain.Entities
[Required]
[Column("NAME", TypeName = "nvarchar(128)")]
public string Name { get; set; }
public required string Name { get; set; }
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
public string CompanyName { get; set; }
public string? CompanyName { get; set; }
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
public string JobTitle { get; set; }
public string? JobTitle { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
public required DateTime AddedWhen { get; init; }
}
}

View File

@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="1.0.0" />
<PackageReference Include="UserManager.Domain" Version="1.0.0" />
</ItemGroup>

View File

@ -1,4 +1,4 @@
import { ApplicationConfig } from '@angular/core';
import { ApplicationConfig, APP_INITIALIZER } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
@ -8,6 +8,7 @@ import { UrlService } from './services/url.service';
import { API_URL } from './tokens/index'
import { HTTP_INTERCEPTORS, provideHttpClient, withFetch } from '@angular/common/http';
import { HttpRequestInterceptor } from './http.interceptor';
import { ConfigurationService } from './services/configuration.service';
export const appConfig: ApplicationConfig = {
providers: [
@ -29,6 +30,12 @@ export const appConfig: ApplicationConfig = {
provide: HTTP_INTERCEPTORS,
useClass: HttpRequestInterceptor,
multi: true
},
{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigurationService) => async () => await configService.ngOnInit(),
deps: [ConfigurationService],
multi: true
}
]
};

View File

@ -1,48 +0,0 @@
<table #table mat-table [dataSource]="data" class="mat-elevation-z8">
@for (colId of displayedColumns; track colId) {
<ng-container matColumnDef="{{colId}}">
<th mat-header-cell *matHeaderCellDef> {{schema[colId].header}} </th>
<td mat-cell *matCellDef="let element"> {{schema[colId].field(element)}} </td>
</ng-container>
}
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
<td mat-cell *matCellDef="let element">
<button mat-icon-button aria-label="expand row"
(click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
@if (expandedElement === element) {
<mat-icon>keyboard_arrow_up</mat-icon>
} @else {
<mat-icon>keyboard_arrow_down</mat-icon>
}
</button>
</td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div class="example-element-diagram">
<div class="example-element-position"> {{"element.position"}} </div>
<div class="example-element-symbol"> {{"element.symbol"}} </div>
<div class="example-element-name"> {{"element.name"}} </div>
<div class="example-element-weight"> {{"element.weight"}} </div>
</div>
<div class="example-element-description">
{{"element.description"}}
<span class="example-element-description-attribution"> -- Wikipedia </span>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;" class="example-element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="expandedElement = expandedElement === element ? null : element">
</tr>
<!--<tr mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpandedRow" class="example-detail-row"></tr>-->
</table>

View File

@ -1,31 +0,0 @@
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}

View File

@ -1,74 +0,0 @@
import { Component, Input, ViewChild } from '@angular/core';
import { EnvelopeReceiverService } from '../../services/envelope-receiver.service';
import { MatTable, MatTableModule } from '@angular/material/table';
import { CommonModule } from '@angular/common'
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-envelope-table',
standalone: true,
imports: [MatTableModule, CommonModule, MatTableModule, MatButtonModule, MatIconModule],
templateUrl: './envelope-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
styleUrl: './envelope-table.component.scss'
})
export class EnvelopeTableComponent {
@Input() data: Array<any> = []
@Input() options?: { min_status?: number; max_status?: number; ignore_status?: number[] }
@Input() displayedColumns: string[] = ['title', 'status', 'type', 'privateMessage', 'addedWhen'];
@Input() schema: Record<string, { header: string; field: (element: any) => any; }> = {
'title': {
header: 'Title',
field: (element: any) => element.envelope.title
},
'status': {
header: 'Status',
field: (element: any) => element.envelope.statusName
},
'type': {
header: 'Type',
field: (element: any) => element.envelope.contractType
},
'privateMessage': {
header: 'Private Message',
field: (element: any) => element.privateMessage
},
'addedWhen': {
header: 'Added When',
field: (element: any) => element.addedWhen
},
}
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
expandedElement: any | null;
@ViewChild(MatTable) table!: MatTable<any>;
constructor(private erService: EnvelopeReceiverService) { }
async ngOnInit() {
if (this.data.length === 0)
this.data = await this.erService.getEnvelopeReceiverAsync(this.options);
}
public updateTable() {
this.table.renderRows();
}
isExpandedRow(index: number, row: any): boolean {
return (row?.envelopeId === this.expandedElement?.envelopeId) && (row?.receiverId === this.expandedElement?.receiverId);
}
}

View File

@ -37,19 +37,19 @@ export class ReceiverInputComponent implements OnInit, OnChanges {
private setupFiltering(): void {
this.filteredOptions = this.control.valueChanges.pipe(
startWith(''),
map(value => this.filter(value || '', this.options)),
map(value => this.filter(value || '', this.options, this.index)),
);
}
control = new FormControl('');
filteredOptions!: Observable<string[]>;
@Input() options: string[] = [];
@Input() filter: (value: string, options: string[]) => string[] = value => {
@Input() filter: (value: string, options: string[], index?: number) => string[] = value => {
const filterValue = value.toLowerCase();
return this.options.filter(option => option.toLowerCase().includes(filterValue));
}
@Input() index?: number;
public get text(): string {
return this.control.value || '';

View File

@ -1,7 +1,7 @@
<table mat-table [dataSource]="receiverData" class="mat-elevation-z8">
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef> Email </th>
<td mat-cell *matCellDef="let element">
<td mat-cell *matCellDef="let element; let i = index">
<receiver-input [options]="receiver_mails" [filter]="receiver_filter"></receiver-input>
</td>
</ng-container>

View File

@ -0,0 +1,59 @@
@if(isFilterable) {
<mat-form-field>
<mat-label>{{filter.label}}</mat-label>
<input matInput (keyup)="applyFilter($event)" [placeholder]="filter.placeholder" #input>
</mat-form-field>
}
<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8" matSort>
@for (column of __columnsToDisplay; track column) {
<ng-container matColumnDef="{{column}}">
@if(isSortable) {
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{schema[column].header}} </th>
}
@else {
<th mat-header-cell *matHeaderCellDef> {{schema[column].header}} </th>
}
<td mat-cell *matCellDef="let element"> {{schema[column].field(element)}} </td>
</ng-container>
}
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
@if(isExpandable) {
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
<td mat-cell *matCellDef="let element">
<button mat-icon-button aria-label="expand row" (click)="toggleExpandedRow(element, $event)">
@if (__expandedElement === element) {
<mat-icon>keyboard_arrow_up</mat-icon>
} @else {
<mat-icon>keyboard_arrow_down</mat-icon>
}
</button>
</td>
</ng-container>
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="__columnsToDisplayWithExpand.length">
<div class="example-element-detail" [@detailExpand]="element == __expandedElement ? 'expanded' : 'collapsed'">
@if(__expandedElement === element){
<ng-content select="[expanded]" detailed></ng-content>
}
</div>
</td>
</ng-container>
}
@if(isExpandable) {
<tr mat-header-row *matHeaderRowDef="__columnsToDisplayWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: __columnsToDisplayWithExpand;" class="example-element-row"
[class.example-expanded-row]="__expandedElement === element" (click)="toggleExpandedRow(element, $event)">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
}
@else {
<tr mat-header-row *matHeaderRowDef="__columnsToDisplay"></tr>
<tr mat-row *matRowDef="let row; columns: __columnsToDisplay;"></tr>
}
</table>
@if(paginatorSizeOptions && paginatorSizeOptions.length > 0) {
<mat-paginator [pageSizeOptions]="paginatorSizeOptions" aria-label="Select page of users"></mat-paginator>
}

View File

@ -0,0 +1,52 @@
table {
width: 100%;
}
tr.example-detail-row {
height: 0;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}
.mat-mdc-form-field {
font-size: 14px;
width: 100%;
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DDTable } from './dd-table.component';
describe('TableExpandableRowsExampleComponent', () => {
let component: DDTable;
let fixture: ComponentFixture<DDTable>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DDTable]
})
.compileComponents();
fixture = TestBed.createComponent(DDTable);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,103 @@
import { AfterViewInit, Component, Input, ViewChild, inject } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatTable, MatTableDataSource, MatTableModule } from '@angular/material/table';
import { ConfigurationService } from '../../../services/configuration.service';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
/**
* @title Table with expandable rows
*/
@Component({
selector: 'dd-table',
styleUrl: 'dd-table.component.scss',
templateUrl: 'dd-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
standalone: true,
imports: [
MatTableModule,
MatButtonModule,
MatIconModule,
MatFormFieldModule,
MatInputModule,
MatTableModule,
MatSort,
MatSortModule,
MatPaginator,
MatPaginatorModule
],
})
export class DDTable implements AfterViewInit {
public readonly dataSource: any = new MatTableDataSource();
@Input() public set columnsToDisplay(value: string[]) {
this.__columnsToDisplay = value;
this.__columnsToDisplayWithExpand = [...value, 'expand'];
}
@Input() public set data(value: any[]) {
this.dataSource.data = value;
}
@Input() schema: Record<string, { header: string; field: (element: any) => any; }> = {}
@Input() paginatorSizeOptions?: number[];
@Input() filter: { label: string, placeholder: string } = { label: '', placeholder: '' }
@Input() isFilterable: boolean = false;
@Input() isExpandable: boolean = false;
@Input() isSortable: boolean = false;
@Input() onToggleExpandedRow: (element: any, event: Event) => Promise<void> = async (element: any, event: Event) => { }
public get data(): any[] {
return this.dataSource.data;
}
__columnsToDisplay: string[] = [];
__columnsToDisplayWithExpand: string[] = [];
__expandedElement!: any;
config: ConfigurationService = inject(ConfigurationService);
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatTable) table!: MatTable<any>;
ngAfterViewInit(): void {
if (this.isSortable)
this.dataSource.sort = this.sort;
if (this.paginatorSizeOptions && this.paginatorSizeOptions.length > 0)
this.dataSource.paginator = this.paginator;
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
update() {
this.table.renderRows();
}
async toggleExpandedRow(element: any, event: Event): Promise<void> {
// first determine the new expanded element, thus it would be possible to use up-to-date
const newExpandedElement = this.__expandedElement === element ? null : element;
// before update the expanded element call the call-back method to show up-to-date component
await this.onToggleExpandedRow(newExpandedElement, event);
// assign expanded element
this.__expandedElement = newExpandedElement;
event.stopPropagation();
}
}

View File

@ -0,0 +1,12 @@
<dd-table [data]="data" [columnsToDisplay]="displayedColumns" [schema]="schema"
[paginatorSizeOptions]="[5, 10, 25, 100]" [filter]="{label: 'Filter', placeholder: ''}"
[onToggleExpandedRow]="onToggleExpandedRow" [isSortable]="true" [isExpandable]="true" [isFilterable]="true">
<mat-tab-group expanded>
<mat-tab label="Emfänger">
<receiver-status-table></receiver-status-table>
</mat-tab>
<mat-tab label="History">
<history-table></history-table>
</mat-tab>
</mat-tab-group>
</dd-table>

View File

@ -0,0 +1,59 @@
/* Structure */
table {
width: 100%;
}
.mat-mdc-form-field {
font-size: 14px;
width: 100%;
margin-top: 10px;
}
/* For expanding table */
table {
width: 100%;
}
tr.example-detail-row {
height: 0;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}

View File

@ -0,0 +1,82 @@
import { AfterViewInit, Component, Input, ViewChild, inject, viewChild } from '@angular/core';
import { EnvelopeService } from '../../../services/envelope.service';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { ConfigurationService } from '../../../services/configuration.service';
import { DDTable } from "../dd-table/dd-table.component";
import { ClearableInputComponent } from '../../clearable-input/clearable-input.component'
import { MatTabsModule } from '@angular/material/tabs';
import { ReceiverStatusTableComponent } from "../receiver-status-table/receiver-status-table.component";
import { HistoryTableComponent } from "../history-table/history-table.component";
import { EnvelopeReceiverService } from '../../../services/envelope-receiver.service';
import { HistoryService } from '../../../services/history.service';
@Component({
selector: 'envelope-table',
standalone: true,
imports: [DDTable, ClearableInputComponent, MatTabsModule, ReceiverStatusTableComponent, HistoryTableComponent],
templateUrl: './envelope-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
styleUrl: './envelope-table.component.scss'
})
export class EnvelopeTableComponent implements AfterViewInit {
@Input() options?: { min_status?: number; max_status?: number; ignore_status?: number[] }
displayedColumns: string[] = ['title', 'status', 'type', 'addedWhen'];
schema: Record<string, { header: string; field: (element: any) => any; }> = {
'title': {
header: 'Title',
field: (element: any) => element.title
},
'status': {
header: 'Status',
field: (element: any) => element.statusName
},
'type': {
header: 'Type',
field: (element: any) => this.config.envelopeTypeTitles[element.contractType - 1]
},
'addedWhen': {
header: 'Added When',
field: (element: any) => element.addedWhen
}
}
data: any[] = [];
@ViewChild(ReceiverStatusTableComponent) rsTable!: ReceiverStatusTableComponent
@ViewChild(HistoryTableComponent) histTable!: HistoryTableComponent
onToggleExpandedRow: (envelope: any, event: Event) => Promise<void> = async (envelope, event) => {
if (envelope === null || envelope === undefined)
return;
var uuid: string = envelope.uuid;
this.rsTable.data = await this.erService.getSecretAsync(uuid);
var id: number = envelope.id;
var refType: number = this.config.referenceType.receiver;
const histories = await this.histService.getHistoryAsync({ envelopeId: id, referenceType: refType, withReceiver: true })
this.histTable.data = histories;
}
private eService: EnvelopeService = inject(EnvelopeService);
private config: ConfigurationService = inject(ConfigurationService);
private readonly erService: EnvelopeReceiverService = inject(EnvelopeReceiverService);
private readonly histService: HistoryService = inject(HistoryService);
async ngAfterViewInit() {
this.data = await this.eService.getEnvelopeAsync(this.options);
}
}

View File

@ -0,0 +1 @@
<dd-table [data]="data" [columnsToDisplay]="columnsToDisplay" [schema]="schema" [isSortable]="true"></dd-table>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HistoryTableComponent } from './history-table.component';
describe('HistoryTableComponent', () => {
let component: HistoryTableComponent;
let fixture: ComponentFixture<HistoryTableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HistoryTableComponent]
})
.compileComponents();
fixture = TestBed.createComponent(HistoryTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,30 @@
import { Component } from '@angular/core';
import { DDTable } from '../dd-table/dd-table.component'
@Component({
selector: 'history-table',
standalone: true,
imports: [DDTable],
templateUrl: './history-table.component.html',
styleUrl: './history-table.component.scss'
})
export class HistoryTableComponent {
data: any[] = [];
schema: Record<string, { header: string; field: (element: any) => any; }> = {
"status": {
"header": "Status",
"field": hist => hist.statusName
},
"user": {
"header": "Benutzer",
"field": hist => hist.userReference
},
"date": {
"header": "Datum",
"field": hist => hist.actionDate
}
}
columnsToDisplay: string[] = ["status", "user", "date"];
}

View File

@ -0,0 +1 @@
<dd-table [data]="data" [columnsToDisplay]="columnsToDisplay" [schema]="schema" [isSortable]="true"></dd-table>

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReceiverStatusTableComponent } from './receiver-status-table.component';
describe('ReceiverStatusTableComponent', () => {
let component: ReceiverStatusTableComponent;
let fixture: ComponentFixture<ReceiverStatusTableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ReceiverStatusTableComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ReceiverStatusTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,30 @@
import { Component } from '@angular/core';
import { DDTable } from '../dd-table/dd-table.component'
@Component({
selector: 'receiver-status-table',
standalone: true,
imports: [DDTable],
templateUrl: './receiver-status-table.component.html',
styleUrl: './receiver-status-table.component.scss'
})
export class ReceiverStatusTableComponent {
data: any[] = [];
schema: Record<string, { header: string; field: (element: any) => any; }> = {
"name": {
"header": "Email Anrede",
"field": (er) => er.name
},
"email": {
"header": "Email",
"field": (er) => er.receiver.emailAddress
},
"access_code": {
"header": "Email",
"field": (er) => er.accessCode
},
}
columnsToDisplay: string[] = ["name", "email", "access_code"];
}

View File

@ -0,0 +1,23 @@
<table mat-table [dataSource]="receiverData" class="mat-elevation-z8">
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef> Email </th>
<td mat-cell *matCellDef="let element; let i = index">
<receiver-input [options]="receiver_mails" [filter]="receiver_filter" [index]="i"></receiver-input>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Anrede Email </th>
<td mat-cell *matCellDef="let element">
<clearable-input [label]="'Anrede Email'" [value]="element.name"></clearable-input>
</td>
</ng-container>
<ng-container matColumnDef="accessCode">
<th mat-header-cell *matHeaderCellDef> Zugriffscode </th>
<td mat-cell *matCellDef="let element"> {{element.accessCode}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

View File

@ -1,15 +1,15 @@
import { Component, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms';
import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatTableModule } from '@angular/material/table';
import { AsyncPipe } from '@angular/common';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { ReceiverService } from '../../services/receiver.service'
import { ReceiverInputComponent } from '../receiver-input/receiver-input.component';
import { ReceiverService } from '../../../services/receiver.service'
import { ReceiverInputComponent } from '../../receiver-input/receiver-input.component';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { ClearableInputComponent } from '../clearable-input/clearable-input.component'
import { ClearableInputComponent } from '../../clearable-input/clearable-input.component'
import { v4 as uuidv4 } from 'uuid';
@Component({
@ -34,24 +34,41 @@ export class ReceiverTableComponent implements OnInit {
constructor(private receiverService: ReceiverService) { }
async ngOnInit() {
this.receiver_mails = await this.receiverService.getReceiverAsync().then((receivers: any[]) => receivers.map(r => r.emailAddress));
const receivers = await this.receiverService.getReceiverAsync();
this.receiver_mails = receivers.map((r: any) => r.emailAddress);
this.last_used_name = receivers.reduce((acc: any, r: any) => {
acc[r.emailAddress] = r.lastUsedName;
return acc;
}, {} as { [key: string]: string | null });
}
receiver_filter: (value: string, options: string[]) => string[] = (value, options) => {
receiver_filter: (value: string, options: string[], index?: number) => string[] = (value, options, index) => {
const filterValue = value.toLowerCase();
// set the name if it is used before
const name = this.last_used_name[value];
if (name && index != null && index != undefined) {
this.receiverData.at(index)!.name = name
}
// !!! do not allow email duplication !!!
var similarMails = this.receiver_mails.filter(m => m.toLocaleLowerCase() === value.toLocaleLowerCase() && m !== value)
if (similarMails.length > 0 && index != undefined) {
this.receiverInputs[index].text = similarMails[0];
}
// if added into last row
if (value.length > 0 && (this.receiverInputs.at(-1)?.lenght ?? 0) > 0) {
this.receiverData.at(-1)!.accessCode = generateAccessCode();
this.receiverData.push({ email: "", name: "", accessCode: "" });
this.update();
}
else if (value.length == 0) {
for (var i = 0; i < this.receiverInputs.length - 1; i++) {
if (this.receiverInputs[i].lenght === 0) {
this.receiverData.splice(i, 1);
this.update();
}
// delete the row with out mail
else if (value.length === 0 && this.receiverInputs.length - 1 !== index) {
if (this.receiverInputs.length > 1 && this.receiverInputs[index!]?.lenght === 0) {
this.receiverData.splice(index!, 1);
this.update();
}
}
@ -59,6 +76,7 @@ export class ReceiverTableComponent implements OnInit {
}
receiver_mails: string[] = [];
last_used_name: { [key: string]: string | null } = {};
@ViewChildren(ReceiverInputComponent) receiverInputsQueryList!: QueryList<ReceiverInputComponent>;
get receiverInputs(): ReceiverInputComponent[] {

View File

@ -5,7 +5,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatStepperModule } from '@angular/material/stepper';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { ReceiverTableComponent } from "../../components/receiver-table/receiver-table.component";
import { ReceiverTableComponent } from "../../components/tables/receiver-table/receiver-table.component";
import { MatIconModule } from '@angular/material/icon';
@Component({

View File

@ -1,10 +1,10 @@
<div id="table">
<mat-tab-group>
<mat-tab label="Offene Umschläge">
<app-envelope-table [options]="{max_status: Status.EnvelopePartlySigned}"></app-envelope-table>
<envelope-table [options]="{max_status: Status.EnvelopePartlySigned}"></envelope-table>
</mat-tab>
<mat-tab label="Abgeschlossene Umschläge">
<app-envelope-table [options]="{min_status: Status.EnvelopeCompletelySigned, ignore_status: [Status.EnvelopeDeleted]}"></app-envelope-table>
<envelope-table [options]="{min_status: Status.EnvelopeCompletelySigned, ignore_status: [Status.EnvelopeDeleted]}"></envelope-table>
</mat-tab>
</mat-tab-group>
</div>

View File

@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { EnvelopeTableComponent } from "../../components/envelope-table/envelope-table.component";
import { EnvelopeTableComponent } from "../../components/tables/envelope-table/envelope-table.component";
import { MatTabsModule } from '@angular/material/tabs';
import { LocalizationService } from '../../services/localization.service';
import { Status } from '../../enums/envelope-const'

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ConfigurationService } from './configuration.service';
describe('ConfigurationService', () => {
let service: ConfigurationService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ConfigurationService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,47 @@
import { Injectable, OnInit, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, firstValueFrom } from 'rxjs';
import { API_URL } from '../tokens/index';
@Injectable({
providedIn: 'root'
})
export class ConfigurationService implements OnInit {
protected url: string;
private _envelopeTypes! : any[];
private _envelopeTypeTitles! : any[];
private _referenceType!: any;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}`;
}
async ngOnInit(): Promise<void> {
const envelopeTypes$: Observable<any[]> = this.http.get<any[]>(`${this.url}/EnvelopeType`)
envelopeTypes$.subscribe({next: res => {
this._envelopeTypes = res;
this._envelopeTypeTitles = res.map(e => e.title);
}});
this.http.get<any>(`${this.url}/History/reference-type`).subscribe({
next: res => this._referenceType = res
})
}
public get envelopeTypes() {
return this._envelopeTypes;
}
public get envelopeTypeTitles() {
return this._envelopeTypeTitles;
}
public get referenceType() {
return this._referenceType;
}
}

View File

@ -27,8 +27,18 @@ export class EnvelopeReceiverService {
return this.http.get<any>(this.url, { params });
}
getEnvelopeReceiverAsync(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Promise<any> {
return firstValueFrom(this.getEnvelopeReceiver(options));
}
getSecret(uuid: string): Observable<any> {
let params = new HttpParams();
params = params.set('uuid', uuid);
return this.http.get<any>(`${this.url}/secret`, { params });
}
getSecretAsync(uuid: string): Promise<any> {
return firstValueFrom(this.getSecret(uuid));
}
}

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { EnvelopeService } from './envelope.service';
describe('EnvelopeService', () => {
let service: EnvelopeService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(EnvelopeService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,33 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, firstValueFrom } from 'rxjs';
import { API_URL } from '../tokens/index';
@Injectable({
providedIn: 'root'
})
export class EnvelopeService {
protected url: string;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/envelope`;
}
public getEnvelope(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Observable<any> {
let params = new HttpParams();
if (options) {
if (options.min_status)
params = params.set('min_status', options.min_status.toString());
if (options.max_status)
params = params.set('max_status', options.max_status.toString());
if (options.ignore_status)
params = params.set('ignore_status', options.ignore_status.join(','));
}
return this.http.get(this.url, { params });
}
public async getEnvelopeAsync(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Promise<any> {
return await firstValueFrom(this.getEnvelope(options));
}
}

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { HistoryService } from './history.service';
describe('HistoryService', () => {
let service: HistoryService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(HistoryService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, firstValueFrom } from 'rxjs';
import { API_URL } from '../tokens/index';
@Injectable({
providedIn: 'root'
})
export class HistoryService {
protected url: string;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/history`;
}
public getHistory(options?: Options): Observable<any> {
let params = new HttpParams();
if (options) {
if (options.envelopeId)
params = params.set('envelopeId', options.envelopeId);
if (options.referenceType != null)
params = params.set('referenceType', options.referenceType);
if (options.userReference)
params = params.set('userReference', options.userReference);
if (options.withReceiver)
params = params.set('withReceiver', options.withReceiver);
if (options.withSender)
params = params.set('withSender', options.withSender);
}
return this.http.get(this.url, { params });
}
public async getHistoryAsync(options?: Options): Promise<any> {
return firstValueFrom(this.getHistory(options));
}
}
class Options {
envelopeId?: number;
userReference?: string;
referenceType: number | null = null;
withSender?: boolean;
withReceiver?: boolean;
}

View File

@ -5,20 +5,20 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
public static class ControllerExtensions
{
public static int? GetId(this ControllerBase controller)
=> int.TryParse(controller.User.FindFirst(ClaimTypes.NameIdentifier)?.Value, out int result)
public static int? GetId(this ClaimsPrincipal user)
=> int.TryParse(user.FindFirst(ClaimTypes.NameIdentifier)?.Value, out int result)
? result : null;
public static string? GetUsername(this ControllerBase controller)
=> controller.User.FindFirst(ClaimTypes.Name)?.Value;
public static string? GetUsername(this ClaimsPrincipal user)
=> user.FindFirst(ClaimTypes.Name)?.Value;
public static string? GetName(this ControllerBase controller)
=> controller.User.FindFirst(ClaimTypes.Surname)?.Value;
public static string? GetName(this ClaimsPrincipal user)
=> user.FindFirst(ClaimTypes.Surname)?.Value;
public static string? GetPrename(this ControllerBase controller)
=> controller.User.FindFirst(ClaimTypes.GivenName)?.Value;
public static string? GetPrename(this ClaimsPrincipal user)
=> user.FindFirst(ClaimTypes.GivenName)?.Value;
public static string? GetEmail(this ControllerBase controller)
=> controller.User.FindFirst(ClaimTypes.Email)?.Value;
public static string? GetEmail(this ClaimsPrincipal user)
=> user.FindFirst(ClaimTypes.Email)?.Value;
}
}

View File

@ -0,0 +1,52 @@
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class EnvelopeController : ControllerBase
{
private readonly ILogger<EnvelopeController> _logger;
private readonly IEnvelopeService _envelopeService;
public EnvelopeController(ILogger<EnvelopeController> logger, IEnvelopeService envelopeService)
{
_logger = logger;
_envelopeService = envelopeService;
}
[Authorize]
[HttpGet]
public async Task<IActionResult> GetCurrentAsync(
[FromQuery] int? min_status = null,
[FromQuery] int? max_status = null,
[FromQuery] params int[] ignore_statuses)
{
try
{
if (User.GetId() is int intId)
return await _envelopeService.ReadByUserAsync(intId, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
else
{
_logger.LogError("Despite successful authorization, the 'api/envelope' route encountered an issue: the user ID is not recognized as an integer. This may be due to the removal of the ID during the creation of the claims list.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -1,11 +1,13 @@
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Common.My.Resources;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[Authorize]
[ApiController]
public class EnvelopeReceiverController : ControllerBase
{
@ -17,19 +19,18 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
_logger = logger;
_erService = envelopeReceiverService;
}
[Authorize]
[HttpGet]
public async Task<IActionResult> GetEnvelopeReceiver([FromQuery] int? min_status = null, [FromQuery] int? max_status = null, [FromQuery] int[]? ignore_status = null)
{
try
{
var username = this.GetUsername();
var username = User.GetUsername();
if (username is null)
{
_logger.LogError(@"Envelope Receiver dto cannot be sent because username claim is null. Potential authentication and authorization error. The value of other claims are [id: {id}], [username: {username}], [name: {name}], [prename: {prename}], [email: {email}].",
this.GetId(), this.GetUsername(), this.GetName(), this.GetPrename(), this.GetEmail());
User.GetId(), User.GetUsername(), User.GetName(), User.GetPrename(), User.GetEmail());
return StatusCode(StatusCodes.Status500InternalServerError);
}
@ -49,5 +50,49 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("receiver-name/{mail}")]
public async Task<IActionResult> GetReceiverName([FromRoute] string mail)
{
try
{
return await _erService.ReadLastUsedReceiverNameByMail(mail).ThenAsync(
Success: res => res is null ? Ok(string.Empty) : Ok(res),
Fail: IActionResult (msg, ntc) =>
{
if (ntc.HasFlag(Flag.NotFound))
return NotFound();
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch(Exception ex)
{
_logger.LogError(ex, "{message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("secret")]
[Authorize]
public async Task<IActionResult> GetSecretAsync([FromQuery] string uuid)
{
try
{
return await _erService.ReadSecretByUuidAsync(uuid: uuid).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch (Exception ex)
{
_logger.LogError(ex, "{message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -0,0 +1,43 @@
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Net.Mail;
using System.Security.Cryptography.Xml;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EnvelopeTypeController : ControllerBase
{
private readonly ILogger<EnvelopeTypeController> _logger;
private readonly IEnvelopeTypeService _service;
public EnvelopeTypeController(ILogger<EnvelopeTypeController> logger, IEnvelopeTypeService service)
{
_logger = logger;
_service = service;
}
[HttpGet]
public async Task<IActionResult> GetAllAsync()
{
try
{
return await _service.ReadAllAsync().ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return ntc.HasFlag(Flag.NotFound) ? NotFound() : StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch (Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
}

View File

@ -0,0 +1,73 @@
using EnvelopeGenerator.Application.Contracts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class HistoryController : ControllerBase
{
private readonly ILogger<HistoryController> _logger;
private readonly IEnvelopeHistoryService _service;
public HistoryController(ILogger<HistoryController> logger, IEnvelopeHistoryService service)
{
_logger = logger;
_service = service;
}
[HttpGet("reference-type")]
[Authorize]
public IActionResult GetReferenceTypes()
{
// Enum to Key-Value pair
var referenceTypes = Enum.GetValues(typeof(ReferenceType))
.Cast<ReferenceType>()
.ToDictionary(rt =>
{
var key = rt.ToString();
var keyAsCamelCase = char.ToLower(key[0]) + key[1..];
return keyAsCamelCase;
}, rt => (int)rt);
return Ok(referenceTypes);
}
[HttpGet]
[Authorize]
public async Task<IActionResult> GetAllAsync([FromQuery] int? envelopeId = null, [FromQuery] string? userReference = null, [FromQuery] int? referenceType = null, [FromQuery] bool withSender = false, [FromQuery] bool withReceiver = false)
{
ReferenceType? refTypEnum = null;
if (referenceType is int refTypInt)
if (Enum.IsDefined(typeof(ReferenceType), refTypInt))
refTypEnum = (ReferenceType)refTypInt;
else
throw new ArgumentException($"The provided referenceType '{referenceType}' is not valid. It must correspond to a valid value in the {nameof(ReferenceType)} enum.");
switch(referenceType)
{
case (int)ReferenceType.Receiver:
withReceiver = true;
break;
case (int)ReferenceType.Sender:
withSender = true;
break;
}
var histories = await _service.ReadAsync(
envelopeId: envelopeId,
userReference: userReference,
referenceType: refTypEnum,
withSender: withSender,
withReceiver: withReceiver);
return Ok(histories);
}
}
}

View File

@ -17,8 +17,6 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
}
[HttpGet]
public async Task<IActionResult> Get([FromQuery] string? emailAddress = null, [FromQuery] string? signature = null)
{

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" />
<PackageReference Include="DigitalData.Core.API" Version="1.0.2.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
<PackageReference Include="DigitalData.Core.API" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.15" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="System.DirectoryServices" Version="7.0.1" />

View File

@ -3,7 +3,7 @@ using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Infrastructure.Contracts
{
public interface IEnvelopeReceiverRepository : ICRUDRepository<EnvelopeReceiver, object>
public interface IEnvelopeReceiverRepository : ICRUDRepository<EnvelopeReceiver, (int Envelope, int Receiver)>
{
Task<IEnumerable<EnvelopeReceiver>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false);
@ -20,5 +20,7 @@ namespace EnvelopeGenerator.Infrastructure.Contracts
Task<string?> ReadAccessCodeByIdAsync(int envelopeId, int receiverId);
Task<IEnumerable<EnvelopeReceiver>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
Task<EnvelopeReceiver?> ReadLastByReceiver(string email);
}
}

View File

@ -8,5 +8,7 @@ namespace EnvelopeGenerator.Infrastructure.Contracts
Task<IEnumerable<Envelope>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false);
Task<Envelope?> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false);
Task<IEnumerable<Envelope>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
}
}

View File

@ -1,14 +1,77 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
using DigitalData.UserManager.Domain.Entities;
using DigitalData.UserManager.Infrastructure;
using DigitalData.UserManager.Infrastructure.Contracts;
using EnvelopeGenerator.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Group = DigitalData.UserManager.Domain.Entities.Group;
using Module = DigitalData.UserManager.Domain.Entities.Module;
using DigitalData.EmailProfilerDispatcher;
namespace EnvelopeGenerator.Infrastructure
{
public class EGDbContext : DbContext
//TODO: Adding EmailOut instead of EmailOut.Abst is not correct for the arch. Re-design EmailPut consedering this. IMailDbContext shoud move to Abstraction layer (hint: in this case using DBSet in abst. will be problem because entity framework will have to be added.
public class EGDbContext : DbContext, IUserManagerDbContext, IMailDbContext
{
public DbSet<UserReceiver> UserReceivers { get; set; }
public DbSet<Config> Configs { get; set; }
public DbSet<EnvelopeReceiver> EnvelopeReceivers { get; set; }
public DbSet<Envelope> Envelopes { get; set; }
public DbSet<DocumentReceiverElement> DocumentReceiverElements { get; set; }
public DbSet<DocumentStatus> DocumentStatus { get; set; }
public DbSet<EmailTemplate> EmailTemplate { get; set; }
public DbSet<EnvelopeCertificate> EnvelopeCertificates { get; set; }
public DbSet<EnvelopeDocument> EnvelopeDocument { get; set; }
public DbSet<EnvelopeHistory> EnvelopeHistories { get; set; }
public DbSet<EnvelopeType> EnvelopeTypes { get; set; }
public DbSet<Receiver> Receivers { get; set; }
public DbSet<GroupOfUser> GroupOfUsers { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<ModuleOfUser> ModuleOfUsers { get; set; }
public DbSet<Module> Modules { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UserRep> UserReps { get; set; }
public DbSet<EmailOut> EMailOuts { get; set; }
public EGDbContext(DbContextOptions<EGDbContext> options) : base(options)
{
UserReceivers = Set<UserReceiver>();
Configs = Set<Config>();
EnvelopeReceivers = Set<EnvelopeReceiver>();
Envelopes = Set<Envelope>();
DocumentReceiverElements = Set<DocumentReceiverElement>();
DocumentStatus = Set<DocumentStatus>();
EnvelopeCertificates = Set<EnvelopeCertificate>();
EnvelopeDocument = Set<EnvelopeDocument>();
EnvelopeHistories = Set<EnvelopeHistory>();
EnvelopeTypes = Set<EnvelopeType>();
Receivers = Set<Receiver>();
GroupOfUsers = Set<GroupOfUser>();
Groups = Set<Group>();
ModuleOfUsers = Set<ModuleOfUser>();
Modules = Set<Module>();
Users = Set<User>();
UserReps = Set<UserRep>();
EMailOuts = Set<EmailOut>();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)

View File

@ -7,15 +7,16 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="1.0.1.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.15" />
<PackageReference Include="UserManager.Infrastructure" Version="1.0.0" />
<PackageReference Include="UserManager.Infrastructure" Version="2.0.0" />
</ItemGroup>
<ItemGroup>

View File

@ -1,5 +1,4 @@
using DigitalData.Core.Infrastructure;
using DigitalData.UserManager.Infrastructure.Repositories;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.EntityFrameworkCore;
@ -8,7 +7,7 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
{
public class ConfigRepository : CRUDRepository<Config, int, EGDbContext>, IConfigRepository
{
public ConfigRepository(EGDbContext dbContext) : base(dbContext)
public ConfigRepository(EGDbContext dbContext) : base(dbContext, dbContext.Configs)
{
}

View File

@ -1,5 +1,4 @@
using DigitalData.Core.Infrastructure;
using DigitalData.UserManager.Infrastructure.Repositories;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
@ -7,7 +6,7 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
{
public class DocumentReceiverElementRepository : CRUDRepository<DocumentReceiverElement, int, EGDbContext>, IDocumentReceiverElementRepository
{
public DocumentReceiverElementRepository(EGDbContext dbContext) : base(dbContext)
public DocumentReceiverElementRepository(EGDbContext dbContext) : base(dbContext, dbContext.DocumentReceiverElements)
{
}
}

View File

@ -7,7 +7,7 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
{
public class DocumentStatusRepository : CRUDRepository<DocumentStatus, int, EGDbContext>, IDocumentStatusRepository
{
public DocumentStatusRepository(EGDbContext dbContext) : base(dbContext)
public DocumentStatusRepository(EGDbContext dbContext) : base(dbContext, dbContext.DocumentStatus)
{
}
}

Some files were not shown because too many files have changed in this diff Show More