Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #222

Merged
merged 6 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/Application/Features/Documents/DTOs/DocumentDto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace Cfo.Cats.Application.Features.Documents.DTOs;
[Description("Documents")]
public class DocumentDto
{
[Description("Id")] public int Id { get; set; }
[Description("Id")] public Guid? Id { get; set; }

[Description("Title")] public string? Title { get; set; }
[Description("File Name")] public string? Title { get; set; }

[Description("Description")] public string? Description { get; set; }

Expand All @@ -23,6 +23,9 @@ public class DocumentDto
[Description("Tenant Name")] public string? TenantName { get; set; }

[Description("Content")] public string? Content { get; set; }
[Description("Created By")] public string CreatedBy { get; set; } = string.Empty;
[Description("Created By Name")] public string CreatedByName { get; set; } = string.Empty;
[Description("Created Date")] public DateTime Created { get; set; }

[Description("Owner")] public ApplicationUserDto? Owner { get; set; }

Expand All @@ -31,7 +34,8 @@ private class Mapping : Profile
public Mapping()
{
CreateMap<Document, DocumentDto>(MemberList.None)
.ForMember(x => x.TenantName, s => s.MapFrom(y => y.Tenant!.Name));
.ForMember(x => x.TenantName, s => s.MapFrom(y => y.Tenant!.Name))
.ForMember(x => x.CreatedByName, s => s.MapFrom(y => y.Owner!.DisplayName));
CreateMap<DocumentDto, Document>(MemberList.None)
.ForMember(x => x.Tenant, s => s.Ignore())
.ForMember(x => x.Owner, s => s.Ignore());
Expand Down
47 changes: 47 additions & 0 deletions src/Application/Features/Documents/Queries/GetByParticipantId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Cfo.Cats.Application.Common.Security;
using Cfo.Cats.Application.Common.Validators;
using Cfo.Cats.Application.Features.Documents.DTOs;
using Cfo.Cats.Application.Features.Participants.DTOs;
using Cfo.Cats.Application.SecurityConstants;
using DocumentFormat.OpenXml.InkML;
using System.Threading.Tasks;

namespace Cfo.Cats.Application.Features.Documents.Queries;
public static class GetByParticipantId
{
[RequestAuthorize(Policy = SecurityPolicies.AuthorizedUser)]

public class Query : IRequest<Result<DocumentDto[]>>
{
public required string ParticipantId { get; set; }
}

public class Handler(IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler<Query, Result<DocumentDto[]>>
{
public async Task<Result<DocumentDto[]>> Handle(Query request, CancellationToken cancellationToken)
{
string likeCriteria = string.Format(@"Files/{0}%", request.ParticipantId);
var query = unitOfWork.DbContext.Documents
.Where(d => EF.Functions.Like(d.URL, likeCriteria));

var documents = await query.ProjectTo<DocumentDto>(mapper.ConfigurationProvider)
.ToArrayAsync(cancellationToken) ?? [];

return Result<DocumentDto[]>.Success(documents);
}
}
public class Validator : AbstractValidator<Query>
{
public Validator()
{
RuleFor(x => x.ParticipantId.ToString())
.NotEmpty()
.MinimumLength(9)
.MaximumLength(9)
.Matches(ValidationConstants.AlphaNumeric)
.WithMessage(string.Format(ValidationConstants.AlphaNumericMessage, "Participant Id"));

}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Handler(IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler<Q
public async Task<Result<EnrolmentQueueEntryDto>> Handle(Query request, CancellationToken cancellationToken)
{
var entry = await unitOfWork.DbContext.EnrolmentPqaQueue
.Where(a => a.Id == request.Id && request.CurrentUser!.TenantId!.StartsWith(a.TenantId))
.Where(a => a.Id == request.Id && a.TenantId.StartsWith(request.CurrentUser!.TenantId!))
.ProjectTo<EnrolmentQueueEntryDto>(mapper.ConfigurationProvider)
.FirstOrDefaultAsync(cancellationToken);

Expand Down
2 changes: 1 addition & 1 deletion src/Server.UI/Pages/Dashboard/Dashboard.razor
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6">
Pending Cases
Enrolling Cases
</MudText>
</CardHeaderContent>
</MudCardHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,3 @@
public string Token { get; set; } = "";
}
}
using Cfo.Cats.Application.Features.Identity.Notifications.IdentityEvents;
116 changes: 116 additions & 0 deletions src/Server.UI/Pages/Participants/Components/CaseDocuments.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
@using Cfo.Cats.Application.Common.Interfaces.Identity
@using Cfo.Cats.Server.UI.Pages.Participants.Components
@using Cfo.Cats.Application.Features.Participants.DTOs
@using Cfo.Cats.Application.Features.Documents.DTOs
@using Cfo.Cats.Application.Features.Participants.Queries
@using Cfo.Cats.Application.Features.Documents.Queries
@using Cfo.Cats.Application.SecurityConstants
@using System.Net.Http.Json
@using Humanizer

@inherits CatsComponentBase

@inject IUserService UserService
@inject IStringLocalizer<CaseDocuments> L


@attribute [Authorize(Policy = SecurityPolicies.AuthorizedUser)]

<style>
.mud-table-toolbar {
height: 120px !important;
}
</style>
<MudDataGrid T="DocumentDto" FixedHeader="true" Loading="_loading"
FixedFooter="true"
Virtualize="true"
Height="calc(100vh - 330px)"
Items="@_documents"
Hover="true">

<Columns>
<TemplateColumn CellStyle="width:60px" Title="@ConstantString.Actions" Sortable="false">
<CellTemplate>
<MudMenu Icon="@Icons.Material.Filled.Edit" Variant="Variant.Filled" Size="Size.Small"
Dense="true" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" IconColor="Color.Info" AnchorOrigin="Origin.CenterLeft">
<MudMenuItem OnClick="@(() => OpenDocumentDialog(context.Item))">@ConstantString.View</MudMenuItem>
</MudMenu>
</CellTemplate>
</TemplateColumn>
<PropertyColumn Property="x => x.Title" Title="@L[_currentDto.GetMemberDescription(x => x.Title)]" />
<PropertyColumn Property="x => x.Description" Title="@L[_currentDto.GetMemberDescription(x => x.Description)]" />
<PropertyColumn Property="x => x.CreatedBy" Title="@L[_currentDto.GetMemberDescription(x => x.CreatedBy)]">
<CellTemplate>
<div>
<MudText Typo="Typo.body2">@context.Item.CreatedByName</MudText>
<MudText Typo="Typo.body2">@context.Item.Created.Humanize()</MudText>
</div>
</CellTemplate>
</PropertyColumn>
<PropertyColumn Property="x => x.TenantId" Title="@L[_currentDto.GetMemberDescription(x => x.TenantName)]">
<CellTemplate>
<div>
<MudText Typo="Typo.body2">@context.Item.TenantName</MudText>
<MudText Typo="Typo.body2" Class="mud-text-secondary">@context.Item.TenantId</MudText>
</div>
</CellTemplate>
</PropertyColumn>
</Columns>
<NoRecordsContent>
<MudText>@ConstantString.NoRecords</MudText>
</NoRecordsContent>
<LoadingContent>
<MudText>@ConstantString.Loading</MudText>
</LoadingContent>
</MudDataGrid>


@code {
bool _loading = true;
private DocumentDto[] _documents = [];
private DocumentDto _currentDto = new() { Id = Guid.Empty };

[Parameter]
[EditorRequired]
public string ParticipantId { get; set; } = default!;

[CascadingParameter]
public UserProfile? UserProfile { get; set; } = null!;

protected Guid SelectedDocument { get; set; } = Guid.Empty;


protected override async Task OnInitializedAsync()
{
try
{
if (String.IsNullOrWhiteSpace(ParticipantId) == false)
{
_documents = await GetNewMediator().Send(new GetByParticipantId.Query()
{
ParticipantId = ParticipantId
});
}
}finally{
_loading = false;
}
}

public async Task OpenDocumentDialog(DocumentDto item)
{
await DialogService.ShowAsync<ViewDocumentDialog>(
"Document",
new DialogParameters<ViewDocumentDialog>()
{
{ x => x.Model, item }
},
new DialogOptions
{
MaxWidth = MaxWidth.ExtraExtraLarge,
Position=DialogPosition.Center,
FullWidth = true,
CloseButton = true,
CloseOnEscapeKey = true,
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
@using Cfo.Cats.Application.Common.Interfaces.Identity
@using Cfo.Cats.Server.UI.Pages.Participants.Components
@using Cfo.Cats.Application.Features.Participants.DTOs
@using Cfo.Cats.Application.Features.Documents.DTOs
@using Cfo.Cats.Application.Features.Participants.Queries
@using Cfo.Cats.Application.Features.Documents.Queries
@using Cfo.Cats.Application.SecurityConstants
@inherits CatsComponentBase

@inject IValidationService Validator

<style>
.full-size-object {
width: 100%;
height: 100%;
}
</style>

@if (Model is not null)
{
<MudDialog Style="height: 100%">
<TitleContent>
<MudText Typo="Typo.h6">
<MudIcon Icon="@Icons.Material.Filled.DocumentScanner" Class="mr-3" />
@Model.Title
</MudText>
</TitleContent>
<DialogContent>
@if (fileBase64 != null && extension!.Equals("pdf", StringComparison.CurrentCultureIgnoreCase))
{
<object data="data:application/pdf;base64,@fileBase64" type="application/pdf" class="full-size-object">
<p>PDF cannot be displayed.</p>
</object>
}
else if (IsFileRejected)
{
<MudText Typo="Typo.caption">
File cannot be displayed. Please contact support.
</MudText>
}
else
{
<MudLoading Loading="true" />
}
</DialogContent>
<DialogActions>
<MudButton OnClick="Cancel">@ConstantString.Close</MudButton>
</DialogActions>
</MudDialog>
}



@code {
[CascadingParameter] private MudDialogInstance MudDialog { get; set; } = default!;

[Parameter, EditorRequired]
public required DocumentDto Model { get; set; }
private bool IsFileRejected { get; set; }
private string? fileBase64;
private string? extension;
private void Cancel()
{
MudDialog.Cancel();
}
protected override async Task OnInitializedAsync()
{
Guid documentId = Model.Id!.Value;
if (documentId != Guid.Empty)
{
var query = new GetDocumentById.Query()
{
Id = documentId
};

var result = await GetNewMediator().Send(query);
if (result.Succeeded)
{
IsFileRejected = false;
using (var memoryStream = new MemoryStream())
{
await result.Data!.FileStream.CopyToAsync(memoryStream);
var bytes = memoryStream.ToArray();
fileBase64 = Convert.ToBase64String(bytes);
}
extension = result.Data!.FileExtension;
}
else
{
IsFileRejected = true;
}
}
}
}
3 changes: 3 additions & 0 deletions src/Server.UI/Pages/Participants/Participant.razor
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@
<MudTabPanel Text="Bio">
<CaseBio ParticipantId="@Id" />
</MudTabPanel>
<MudTabPanel Text="Documents">
<CaseDocuments ParticipantId="@Id" />
</MudTabPanel>
<MudTabPanel Text="Pathway Plan">
<CasePathwayPlan ParticipantId="@Id" OnUpdate="Refresh" />
</MudTabPanel>
Expand Down
Loading