diff --git a/source/backend/api/Areas/Admin/Controllers/RoleController.cs b/source/backend/api/Areas/Admin/Controllers/RoleController.cs index f811bbf06a..e244c5b32f 100644 --- a/source/backend/api/Areas/Admin/Controllers/RoleController.cs +++ b/source/backend/api/Areas/Admin/Controllers/RoleController.cs @@ -75,6 +75,23 @@ public IActionResult GetRoles(int page = 1, int quantity = 10, string name = nul var result = _mapper.Map>(paged); return new JsonResult(result); } + + /// + /// GET - Returns a role for the specified 'key' from the datasource. + /// + /// The unique 'key' for the role to return. + /// The role requested. + [HttpGet("{key}")] + [Produces("application/json")] + [ProducesResponseType(typeof(Model.RoleModel), 200)] + [ProducesResponseType(typeof(Api.Models.ErrorResponseModel), 400)] + [SwaggerOperation(Tags = new[] { "admin-role" })] + public IActionResult GetRole(Guid key) + { + var entity = _roleRepository.GetByKey(key); + var role = _mapper.Map(entity); + return new JsonResult(role); + } #endregion } } diff --git a/source/backend/api/Areas/Documents/DocumentRelationshipController.cs b/source/backend/api/Areas/Documents/DocumentRelationshipController.cs index bea9980d92..c6a038365c 100644 --- a/source/backend/api/Areas/Documents/DocumentRelationshipController.cs +++ b/source/backend/api/Areas/Documents/DocumentRelationshipController.cs @@ -106,6 +106,10 @@ public IActionResult GetRelationshipDocuments(DocumentRelationType relationshipT var projectDocuments = _documentFileService.GetFileDocuments(FileType.Project, long.Parse(parentId)); var mappedProjectDocuments = _mapper.Map>(projectDocuments); return new JsonResult(mappedProjectDocuments); + case DocumentRelationType.ManagementFiles: + var managementDocuments = _documentFileService.GetFileDocuments(FileType.Management, long.Parse(parentId)); + var mappedPropertyActivityDocuments = _mapper.Map>(managementDocuments); + return new JsonResult(mappedPropertyActivityDocuments); default: throw new BadRequestException("Relationship type not valid for retrieve."); } @@ -135,6 +139,7 @@ public async Task UploadDocumentWithParent( DocumentRelationType.Templates => await _formDocumentService.UploadFormDocumentTemplateAsync(parentId, uploadRequest), DocumentRelationType.Projects => await _documentFileService.UploadProjectDocumentAsync(long.Parse(parentId), uploadRequest), DocumentRelationType.Leases => await _documentFileService.UploadLeaseDocumentAsync(long.Parse(parentId), uploadRequest), + DocumentRelationType.ManagementFiles => await _documentFileService.UploadPropertyActivityDocumentAsync(long.Parse(parentId), uploadRequest), _ => throw new BadRequestException("Relationship type not valid for upload."), }; @@ -176,6 +181,10 @@ public async Task DeleteDocumentRelationship(DocumentRelationType var projectRelationship = _mapper.Map(model); var projectResult = await _documentFileService.DeleteProjectDocumentAsync(projectRelationship); return new JsonResult(projectResult); + case DocumentRelationType.ManagementFiles: + var propertyActivityRelationship = _mapper.Map(model); + var propertyActivityResult = await _documentFileService.DeletePropertyActivityDocumentAsync(propertyActivityRelationship); + return new JsonResult(propertyActivityResult); default: throw new BadRequestException("Relationship type not valid for delete."); } diff --git a/source/backend/api/Constants/DocumentRelationType.cs b/source/backend/api/Constants/DocumentRelationType.cs index dd94ab253e..4dd0c4c6dd 100644 --- a/source/backend/api/Constants/DocumentRelationType.cs +++ b/source/backend/api/Constants/DocumentRelationType.cs @@ -16,5 +16,7 @@ public enum DocumentRelationType Leases, [EnumMember(Value = "projects")] Projects, + [EnumMember(Value = "managementfiles")] + ManagementFiles, } } diff --git a/source/backend/api/Constants/FileType.cs b/source/backend/api/Constants/FileType.cs index 6dfc274bff..7c39c621bb 100644 --- a/source/backend/api/Constants/FileType.cs +++ b/source/backend/api/Constants/FileType.cs @@ -14,6 +14,8 @@ public enum FileType Project, [EnumMember(Value = "lease")] Lease, + [EnumMember(Value = "management")] + Management, [EnumMember(Value = "unknown")] // Used in tests/logic only. This does not correspond to a valid file type in the db. Unknown, } diff --git a/source/backend/api/Models/Concepts/Document/DocumentRelationshipMap.cs b/source/backend/api/Models/Concepts/Document/DocumentRelationshipMap.cs index 5330b8dd24..1d69f820aa 100644 --- a/source/backend/api/Models/Concepts/Document/DocumentRelationshipMap.cs +++ b/source/backend/api/Models/Concepts/Document/DocumentRelationshipMap.cs @@ -73,6 +73,20 @@ public void Register(TypeAdapterConfig config) .Map(dest => dest.FileId, src => src.ParentId) .Map(dest => dest.DocumentId, src => src.Document.Id) .Map(dest => dest.Document, src => src.Document); + + + config.NewConfig() + .Map(dest => dest.Id, src => src.Internal_Id) + .Map(dest => dest.ParentId, src => src.FileId) + .Map(dest => dest.Document, src => src.Document) + .Map(dest => dest.RelationshipType, src => DocumentRelationType.ManagementFiles) + .Inherits(); + + config.NewConfig() + .Map(dest => dest.Internal_Id, src => src.Id) + .Map(dest => dest.FileId, src => src.ParentId) + .Map(dest => dest.DocumentId, src => src.Document.Id) + .Map(dest => dest.Document, src => src.Document); } } } diff --git a/source/backend/api/Services/DocumentFileService.cs b/source/backend/api/Services/DocumentFileService.cs index b5ee5029c1..7d64e53e85 100644 --- a/source/backend/api/Services/DocumentFileService.cs +++ b/source/backend/api/Services/DocumentFileService.cs @@ -26,6 +26,7 @@ public class DocumentFileService : BaseService, IDocumentFileService private readonly IProjectRepository _projectRepository; private readonly IDocumentRepository _documentRepository; private readonly ILeaseRepository _leaseRepository; + private readonly IPropertyActivityDocumentRepository _propertyActivityDocumentRepository; private readonly IMapper mapper; public DocumentFileService( @@ -37,7 +38,8 @@ public DocumentFileService( IMapper mapper, IProjectRepository projectRepository, IDocumentRepository documentRepository, - ILeaseRepository leaseRepository) + ILeaseRepository leaseRepository, + IPropertyActivityDocumentRepository propertyActivityDocumentRepository) : base(user, logger) { this.acquisitionFileDocumentRepository = acquisitionFileDocumentRepository; @@ -47,6 +49,7 @@ public DocumentFileService( _projectRepository = projectRepository; _documentRepository = documentRepository; _leaseRepository = leaseRepository; + _propertyActivityDocumentRepository = propertyActivityDocumentRepository; } public IList GetFileDocuments(FileType fileType, long fileId) @@ -69,6 +72,9 @@ public IList GetFileDocuments(FileType fileType, long fileId) case FileType.Lease: this.User.ThrowIfNotAuthorized(Permissions.LeaseView); return _leaseRepository.GetAllLeaseDocuments(fileId).Select(f => f as T).ToArray(); + case FileType.Management: + this.User.ThrowIfNotAuthorized(Permissions.ManagementView); + return _propertyActivityDocumentRepository.GetAllByPropertyActivity(fileId).Select(f => f as T).ToArray(); default: throw new BadRequestException("FileT type not valid to get documents."); } @@ -188,6 +194,34 @@ public async Task UploadLeaseDocumentAsync(l return relationshipResponse; } + public async Task UploadPropertyActivityDocumentAsync(long propertyActivityId, DocumentUploadRequest uploadRequest) + { + this.Logger.LogInformation("Uploading document for single Property Activity"); + this.User.ThrowIfNotAuthorized(Permissions.DocumentAdd, Permissions.ManagementEdit); + + DocumentUploadResponse uploadResult = await documentService.UploadDocumentAsync(uploadRequest); + + DocumentUploadRelationshipResponse relationshipResponse = new() + { + UploadResponse = uploadResult, + }; + + if (uploadResult.Document.Id != 0) + { + PimsPropertyActivityDocument newDocument = new() + { + PimsPropertyActivityId = propertyActivityId, + DocumentId = uploadResult.Document.Id, + }; + newDocument = _propertyActivityDocumentRepository.AddPropertyActivityDocument(newDocument); + _leaseRepository.CommitTransaction(); + + relationshipResponse.DocumentRelationship = mapper.Map(newDocument); + } + + return relationshipResponse; + } + public async Task> DeleteResearchDocumentAsync(PimsResearchFileDocument researchFileDocument) { this.Logger.LogInformation("Deleting PIMS document for single research file"); @@ -259,5 +293,23 @@ public async Task> DeleteLeaseDocumentAsync(PimsLeaseDocu return new ExternalResult() { Status = ExternalResultStatus.NotExecuted }; } } + + public async Task> DeletePropertyActivityDocumentAsync(PimsPropertyActivityDocument propertyActivityDocument) + { + this.Logger.LogInformation("Deleting PIMS document for single Property Activity"); + this.User.ThrowIfNotAuthorized(Permissions.ManagementDelete); + + var relationshipCount = _documentRepository.DocumentRelationshipCount(propertyActivityDocument.DocumentId); + if (relationshipCount == 1) + { + return await documentService.DeleteDocumentAsync(propertyActivityDocument.Document); + } + else + { + _propertyActivityDocumentRepository.DeletePropertyActivityDocument(propertyActivityDocument); + _propertyActivityDocumentRepository.CommitTransaction(); + return new ExternalResult() { Status = ExternalResultStatus.NotExecuted }; + } + } } } diff --git a/source/backend/api/Services/DocumentService.cs b/source/backend/api/Services/DocumentService.cs index d7537d610b..638e08120f 100644 --- a/source/backend/api/Services/DocumentService.cs +++ b/source/backend/api/Services/DocumentService.cs @@ -102,6 +102,9 @@ public IList GetPimsDocumentTypes(DocumentRelationType relation case DocumentRelationType.Projects: categoryType = "PROJECT"; break; + case DocumentRelationType.ManagementFiles: + categoryType = "MANAGEMENT"; + break; default: throw new InvalidDataException("The requested category relationship does not exist"); } diff --git a/source/backend/api/Services/IDocumentFileService.cs b/source/backend/api/Services/IDocumentFileService.cs index 24222d2fa2..6f72b5e304 100644 --- a/source/backend/api/Services/IDocumentFileService.cs +++ b/source/backend/api/Services/IDocumentFileService.cs @@ -23,6 +23,8 @@ public IList GetFileDocuments(FileType fileType, long fileId) Task UploadProjectDocumentAsync(long projectId, DocumentUploadRequest uploadRequest); + Task UploadPropertyActivityDocumentAsync(long propertyActivityId, DocumentUploadRequest uploadRequest); + Task> DeleteResearchDocumentAsync(PimsResearchFileDocument researchFileDocument); Task> DeleteAcquisitionDocumentAsync(PimsAcquisitionFileDocument acquisitionFileDocument); @@ -30,5 +32,7 @@ public IList GetFileDocuments(FileType fileType, long fileId) Task> DeleteProjectDocumentAsync(PimsProjectDocument projectDocument); Task> DeleteLeaseDocumentAsync(PimsLeaseDocument leaseDocument); + + Task> DeletePropertyActivityDocumentAsync(PimsPropertyActivityDocument propertyActivityDocument); } } diff --git a/source/backend/api/Startup.cs b/source/backend/api/Startup.cs index 50d767b76b..4381ca7ba0 100644 --- a/source/backend/api/Startup.cs +++ b/source/backend/api/Startup.cs @@ -1,3 +1,4 @@ + using System; using System.Collections.Generic; using System.Data.SqlClient; diff --git a/source/backend/dal/Helpers/Extensions/ServiceCollectionExtensions.cs b/source/backend/dal/Helpers/Extensions/ServiceCollectionExtensions.cs index e009d1acaf..40a5e3412f 100644 --- a/source/backend/dal/Helpers/Extensions/ServiceCollectionExtensions.cs +++ b/source/backend/dal/Helpers/Extensions/ServiceCollectionExtensions.cs @@ -75,6 +75,7 @@ public static IServiceCollection AddPimsDalRepositories(this IServiceCollection repositories.AddScoped(); repositories.AddScoped(); repositories.AddScoped(); + repositories.AddScoped(); return repositories; // TODO: PSP-4424 Use reflection to find all Repositories. } diff --git a/source/backend/dal/Repositories/DocumentRepository.cs b/source/backend/dal/Repositories/DocumentRepository.cs index fd901f9484..ea3d412612 100644 --- a/source/backend/dal/Repositories/DocumentRepository.cs +++ b/source/backend/dal/Repositories/DocumentRepository.cs @@ -94,6 +94,7 @@ public bool Delete(PimsDocument document) .Include(d => d.PimsProjectDocuments) .Include(d => d.PimsFormTypes) .Include(d => d.PimsLeaseDocuments) + .Include(d => d.PimsPropertyActivityDocuments) .Where(d => d.DocumentId == document.Internal_Id) .AsNoTracking() .FirstOrDefault(); @@ -118,6 +119,11 @@ public bool Delete(PimsDocument document) this.Context.PimsLeaseDocuments.Remove(new PimsLeaseDocument() { Internal_Id = pimsLeaseDocument.Internal_Id }); } + foreach (var pimsPropertyActivityDocument in documentToDelete.PimsPropertyActivityDocuments) + { + this.Context.PimsPropertyActivityDocuments.Remove(new PimsPropertyActivityDocument() { Internal_Id = pimsPropertyActivityDocument.Internal_Id }); + } + foreach (var pimsFormTypeDocument in documentToDelete.PimsFormTypes) { var updatedFormType = pimsFormTypeDocument; @@ -139,6 +145,7 @@ public int DocumentRelationshipCount(long documentId) .Include(d => d.PimsProjectDocuments) .Include(d => d.PimsFormTypes) .Include(d => d.PimsLeaseDocuments) + .Include(d => d.PimsPropertyActivityDocuments) .Where(d => d.DocumentId == documentId) .AsNoTracking() .FirstOrDefault(); @@ -147,7 +154,8 @@ public int DocumentRelationshipCount(long documentId) documentRelationships.PimsAcquisitionFileDocuments.Count + documentRelationships.PimsProjectDocuments.Count + documentRelationships.PimsFormTypes.Count + - documentRelationships.PimsLeaseDocuments.Count; + documentRelationships.PimsLeaseDocuments.Count + + documentRelationships.PimsPropertyActivityDocuments.Count; } #endregion diff --git a/source/backend/dal/Repositories/Interfaces/IPropertyActivityFileDocumentRepository.cs b/source/backend/dal/Repositories/Interfaces/IPropertyActivityFileDocumentRepository.cs new file mode 100644 index 0000000000..4eb5d37426 --- /dev/null +++ b/source/backend/dal/Repositories/Interfaces/IPropertyActivityFileDocumentRepository.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Pims.Dal.Entities; + +namespace Pims.Dal.Repositories +{ + /// + /// IPropertyActivityDocumentRepository interface, provides functions to interact with document management files within the datasource. + /// + public interface IPropertyActivityDocumentRepository : IRepository + { + IList GetAllByPropertyActivity(long propertyActivityId); + + PimsPropertyActivityDocument AddPropertyActivityDocument(PimsPropertyActivityDocument propertyActivityDocument); + + bool DeletePropertyActivityDocument(PimsPropertyActivityDocument propertyActivityDocument); + } +} diff --git a/source/backend/dal/Repositories/PropertyActivityFileDocumentRepository.cs b/source/backend/dal/Repositories/PropertyActivityFileDocumentRepository.cs new file mode 100644 index 0000000000..b07156a10d --- /dev/null +++ b/source/backend/dal/Repositories/PropertyActivityFileDocumentRepository.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Pims.Core.Extensions; +using Pims.Dal.Entities; + +namespace Pims.Dal.Repositories +{ + /// + /// PropertyActivityDocumentRepository class, provides a service layer to interact with document activity files within the datasource. + /// + public class PropertyActivityDocumentRepository : BaseRepository, IPropertyActivityDocumentRepository + { + #region Constructors + + /// + /// Creates a new instance of a PropertyActivityDocumentRepository, and initializes it with the specified arguments. + /// + /// + /// + /// + public PropertyActivityDocumentRepository(PimsContext dbContext, ClaimsPrincipal user, ILogger logger) + : base(dbContext, user, logger) + { + } + #endregion + + #region Methods + + /// + /// Get a list of all the document file relationships for a a given property activity. + /// + /// + public IList GetAllByPropertyActivity(long propertyActivityId) + { + return this.Context.PimsPropertyActivityDocuments + .Include(ad => ad.Document) + .ThenInclude(d => d.DocumentStatusTypeCodeNavigation) + .Include(ad => ad.Document) + .ThenInclude(d => d.DocumentType) + .Where(ad => ad.PimsPropertyActivityId == propertyActivityId) + .AsNoTracking() + .ToList(); + } + + /// + /// Adds the passed property document activity file to the database. + /// + /// + /// + public PimsPropertyActivityDocument AddPropertyActivityDocument(PimsPropertyActivityDocument propertyActivityDocument) + { + propertyActivityDocument.ThrowIfNull(nameof(propertyActivityDocument)); + + var newEntry = this.Context.PimsPropertyActivityDocuments.Add(propertyActivityDocument); + if (newEntry.State == EntityState.Added) + { + return newEntry.Entity; + } + else + { + throw new InvalidOperationException("Could not create document"); + } + } + + /// + /// Deletes the passed property document activity file in the database. + /// + /// + /// + public bool DeletePropertyActivityDocument(PimsPropertyActivityDocument propertyActivityDocument) + { + if (propertyActivityDocument == null) + { + throw new ArgumentNullException(nameof(propertyActivityDocument), "propertyActivityDocument cannot be null."); + } + + this.Context.PimsPropertyActivityDocuments.Remove(new PimsPropertyActivityDocument() { PropertyActivityDocumentId = propertyActivityDocument.PropertyActivityDocumentId }); + return true; + } + + #endregion + } +} diff --git a/source/backend/entities/Partials/PropertyActivityDocument.cs b/source/backend/entities/Partials/PropertyActivityDocument.cs new file mode 100644 index 0000000000..c8819352b7 --- /dev/null +++ b/source/backend/entities/Partials/PropertyActivityDocument.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Pims.Dal.Entities +{ + /// + /// PimsDocument for Property Activities. + /// + public partial class PimsPropertyActivityDocument : PimsFileDocument, IBaseAppEntity + { + [NotMapped] + public override long Internal_Id { get => PropertyActivityDocumentId; set => PropertyActivityDocumentId = value; } + + [NotMapped] + public override long FileId { get => this.PimsPropertyActivityId; set => this.PimsPropertyActivityId = value; } + } +} diff --git a/source/backend/tests/unit/api/Controllers/Document/DocumentControllerTest.cs b/source/backend/tests/unit/api/Controllers/Document/DocumentControllerTest.cs new file mode 100644 index 0000000000..3b6fce6a6a --- /dev/null +++ b/source/backend/tests/unit/api/Controllers/Document/DocumentControllerTest.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using FluentAssertions; +using MapsterMapper; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NExpect.Interfaces; +using Pims.Api.Areas.Acquisition.Controllers; +using Pims.Api.Controllers; +using Pims.Api.Helpers.Exceptions; +using Pims.Api.Models.Concepts; +using Pims.Api.Services; +using Pims.Core.Exceptions; +using Pims.Core.Test; +using Pims.Dal.Entities; +using Pims.Dal.Exceptions; +using Pims.Dal.Security; +using Xunit; + +namespace Pims.Api.Test.Controllers +{ + [Trait("category", "unit")] + [Trait("category", "api")] + [Trait("group", "acquisition")] + [ExcludeFromCodeCoverage] + public class DocumentControllerTest + { + #region Variables + private Mock _service; + private Mock _documentFileService; + private DocumentController _controller; + private IMapper _mapper; + #endregion + + public DocumentControllerTest() + { + var helper = new TestHelper(); + this._controller = helper.CreateController(Permissions.DocumentView); + this._mapper = helper.GetService(); + this._service = helper.GetService>(); + this._documentFileService = helper.GetService>(); + } + + #region Tests + [Fact] + public void GetDocumentTypes_Success() + { + // Arrange + this._service.Setup(m => m.GetPimsDocumentTypes()).Returns(new List()); + + // Act + var result = this._controller.GetDocumentTypes(); + + // Assert + this._service.Verify(m => m.GetPimsDocumentTypes(), Times.Once()); + } + + [Fact] + public void UpdateDocumentMetadata_Success() + { + // Arrange + var updateRequest = new DocumentUpdateRequest() { DocumentId = 1 }; + this._service.Setup(m => m.UpdateDocumentAsync(updateRequest)).ReturnsAsync(new DocumentUpdateResponse()); + + // Act + var result = this._controller.UpdateDocumentMetadata(1, updateRequest); + + // Assert + this._service.Verify(m => m.UpdateDocumentAsync(updateRequest), Times.Once()); + } + + [Fact] + public void UpdateDocumentMetadata_InvalidDocumentId() + { + // Arrange + var updateRequest = new DocumentUpdateRequest() { DocumentId = 2 }; + this._service.Setup(m => m.UpdateDocumentAsync(updateRequest)).ReturnsAsync(new DocumentUpdateResponse()); + + // Act + Func act = async () => await this._controller.UpdateDocumentMetadata(1, updateRequest); + + // Assert + act.Should().Throw(); + } + + [Fact] + public void DownloadWrappedFileDocument_Success() + { + // Arrange + this._service.Setup(m => m.DownloadFileAsync(1, 2)).ReturnsAsync(new Models.ExternalResult()); + + // Act + var result = this._controller.DownloadWrappedFile(1, 2); + + // Assert + this._service.Verify(m => m.DownloadFileAsync(1,2), Times.Once()); + } + + [Fact] + public async Task DownloadFileDocument_Success() + { + // Arrange + this._service.Setup(m => m.DownloadFileAsync(1, 2)).ReturnsAsync(new Models.ExternalResult() { Payload = new Models.Download.FileDownload() { FilePayload = "cmVmYWN0b3IgcHJvcGVydHkgdGFicyB0byB1c2Ugcm91dGVyLCBpbmNsdWRpbmcgbWFuYWdlbWVudC4NCkVuc3VyZSB0aGF0IG1hbmFnZW1lbnQgdGFiIHJlZGlyZWN0cyBiYWNrIHRvIG1hbmFnZW1lbnQgdmlldyBhZnRlciBlZGl0aW5nLg0KDQpkaXNjdXNzIDY4MzkgaW4gZGV2IG1lZXRpbmcgdG1ydw0KDQp3aGF0IGlzIGdvaW5nIG9uIHdpdGggaXNfZGlzYWJsZWQ/IHdoeSBhcmUgd2UgYWRkaW5nIGl0IHRvIGpvaW4gdGFibGVzPw0KDQpjb21tZW50IG9uIHJldmlld2luZyB1aSB3aXRoIGFuYSBkdXJpbmcgY29kZSByZXZpZXcuDQoNCmNsZWFuIHVwIG9sZCBnaXRodWIgYWN0aW9ucyAtIA0KDQptYWtlIGdpdGh1YiBhY3Rpb25zIHRvIHByb2QgYW5kIHVhdCByZXN0cmljdGVkIHRvIGEgc21hbGxlciBncm91cA0KDQptYWtlIHByb2QgYW5kIHVhdCBhY3Rpb25zIGhhdmUgYSBkaXNjbGFpbWVyIHdoZW4gcnVubmluZywgYW5kIHRoZW4gaW5jcmVhc2UgdGhlIHZlcmJvc2l0eSBvZiBsb2dnaW5nIHRvIHRlYW1zIHN1Y2ggdGhhdCB0aGUgb3BlcmF0aW9ucyBjb25kdWN0ZWQgYnkgdGhlIGFjdGlvbiBhcmUgbGFpZCBvdXQgZm9yIG5vbi10ZWNobmljYWwgdXNlcnMuDQoNCg0KDQpyZW1vdmU6IGRiLXNjaG1hLnltbA0KbWF5YmU6IHphcC1zY2FuLnltbCwgdGFnLnltbCwgcmVsZWFzZS55bWwsIGltYWdlLXNjYW4tYW5hbHlzaXMsIGNpLWNkLXBpbXMtbWFzdGVyLnltbCwgYXBwLWxvZ2dpbmcueW1sDQoNCndlIHdvdWxkIGxpa2UgdG8gcmVtb3ZlIHRoZSB2ZXJzaW9uIGJ1bXAgZnJvbSBkZXYgd2hlbiB3ZSBoYXZlIGFuIGFsdGVybmF0ZSB3YXkgb2Ygc2VlaW5nIHRoZSBnaXQgY29tbWl0IG9uIHRoZSBpbWFnZS4NCg0KbmVlZCB0byB1cGRhdGUgZW52IGdlbmVyYXRpb24gdG8gYWZmZWN0IG5ldyBsb2NhdGlvbi4=", Mimetype = "text/plain" } }); + + // Act + var result = await this._controller.DownloadFile(1, 2); + + // Assert + this._service.Verify(m => m.DownloadFileAsync(1, 2), Times.Once()); + result.Should().NotBeNull(); + } + + [Fact] + public async Task DownloadFileDocument_NullAsync() + { + // Arrange + this._service.Setup(m => m.DownloadFileAsync(1, 2)).ReturnsAsync(new Models.ExternalResult() { Payload = null }); + + // Act + var result = await this._controller.DownloadFile(1, 2); + + // Assert + var actionResult = Assert.IsType(result); + } + + [Fact] + public void GetDocumentList_Success() + { + // Arrange + this._service.Setup(m => m.GetStorageDocumentList("", null, null)); + + // Act + var result = this._controller.GetDocumentList(); + + // Assert + this._service.Verify(m => m.GetStorageDocumentList("", null, null), Times.Once()); + } + + [Fact] + public void GetDocumentStorageTypes_Success() + { + // Arrange + this._service.Setup(m => m.GetStorageDocumentTypes("", null, null)); + + // Act + var result = this._controller.GetDocumentStorageTypes(); + + // Assert + this._service.Verify(m => m.GetStorageDocumentTypes("", null, null), Times.Once()); + } + + [Fact] + public void GetDocumentStorageTypeMetadata_Success() + { + // Arrange + this._service.Setup(m => m.GetDocumentTypeMetadataType(1, "", null, null)); + + // Act + var result = this._controller.GetDocumentStorageTypeMetadata(1); + + // Assert + this._service.Verify(m => m.GetDocumentTypeMetadataType(1, "", null, null), Times.Once()); + } + + [Fact] + public void GetDocumentStorageTypeDetail_Success() + { + // Arrange + this._service.Setup(m => m.GetStorageDocumentDetail(1)); + + // Act + var result = this._controller.GetDocumentStorageTypeDetail(1); + + // Assert + this._service.Verify(m => m.GetStorageDocumentDetail(1), Times.Once()); + } + + [Fact] + public void DownloadWrappedFile_Success() + { + // Arrange + this._service.Setup(m => m.DownloadFileLatestAsync(1)).ReturnsAsync(new Models.ExternalResult() { Payload = new Models.Download.FileDownload()}); + + // Act + var result = this._controller.DownloadWrappedFile(1); + + // Assert + this._service.Verify(m => m.DownloadFileLatestAsync(1), Times.Once()); + } + + [Fact] + public void DownloadFile_Success() + { + // Arrange + this._service.Setup(m => m.DownloadFileLatestAsync(1)).ReturnsAsync(new Models.ExternalResult() { Payload = new Models.Download.FileDownload() { FilePayload = "cmVmYWN0b3IgcHJvcGVydHkgdGFicyB0byB1c2Ugcm91dGVyLCBpbmNsdWRpbmcgbWFuYWdlbWVudC4NCkVuc3VyZSB0aGF0IG1hbmFnZW1lbnQgdGFiIHJlZGlyZWN0cyBiYWNrIHRvIG1hbmFnZW1lbnQgdmlldyBhZnRlciBlZGl0aW5nLg0KDQpkaXNjdXNzIDY4MzkgaW4gZGV2IG1lZXRpbmcgdG1ydw0KDQp3aGF0IGlzIGdvaW5nIG9uIHdpdGggaXNfZGlzYWJsZWQ/IHdoeSBhcmUgd2UgYWRkaW5nIGl0IHRvIGpvaW4gdGFibGVzPw0KDQpjb21tZW50IG9uIHJldmlld2luZyB1aSB3aXRoIGFuYSBkdXJpbmcgY29kZSByZXZpZXcuDQoNCmNsZWFuIHVwIG9sZCBnaXRodWIgYWN0aW9ucyAtIA0KDQptYWtlIGdpdGh1YiBhY3Rpb25zIHRvIHByb2QgYW5kIHVhdCByZXN0cmljdGVkIHRvIGEgc21hbGxlciBncm91cA0KDQptYWtlIHByb2QgYW5kIHVhdCBhY3Rpb25zIGhhdmUgYSBkaXNjbGFpbWVyIHdoZW4gcnVubmluZywgYW5kIHRoZW4gaW5jcmVhc2UgdGhlIHZlcmJvc2l0eSBvZiBsb2dnaW5nIHRvIHRlYW1zIHN1Y2ggdGhhdCB0aGUgb3BlcmF0aW9ucyBjb25kdWN0ZWQgYnkgdGhlIGFjdGlvbiBhcmUgbGFpZCBvdXQgZm9yIG5vbi10ZWNobmljYWwgdXNlcnMuDQoNCg0KDQpyZW1vdmU6IGRiLXNjaG1hLnltbA0KbWF5YmU6IHphcC1zY2FuLnltbCwgdGFnLnltbCwgcmVsZWFzZS55bWwsIGltYWdlLXNjYW4tYW5hbHlzaXMsIGNpLWNkLXBpbXMtbWFzdGVyLnltbCwgYXBwLWxvZ2dpbmcueW1sDQoNCndlIHdvdWxkIGxpa2UgdG8gcmVtb3ZlIHRoZSB2ZXJzaW9uIGJ1bXAgZnJvbSBkZXYgd2hlbiB3ZSBoYXZlIGFuIGFsdGVybmF0ZSB3YXkgb2Ygc2VlaW5nIHRoZSBnaXQgY29tbWl0IG9uIHRoZSBpbWFnZS4NCg0KbmVlZCB0byB1cGRhdGUgZW52IGdlbmVyYXRpb24gdG8gYWZmZWN0IG5ldyBsb2NhdGlvbi4=", Mimetype = "text/plain" } }); + + // Act + var result = this._controller.DownloadFile(1); + + // Assert + this._service.Verify(m => m.DownloadFileLatestAsync(1), Times.Once()); + } + + [Fact] + public async Task DownloadFile_NoResultAsync() + { + // Arrange + this._service.Setup(m => m.DownloadFileLatestAsync(1)).ReturnsAsync(new Models.ExternalResult() { Payload = null }); + + // Act + var result = await this._controller.DownloadFile(1); + + // Assert + var actionResult = Assert.IsType(result); + } + + [Fact] + public void GetDocumentMetadata_Success() + { + // Arrange + this._service.Setup(m => m.GetStorageDocumentMetadata(1, "", null, null)); + + // Act + var result = this._controller.GetDocumentMetadata(1); + + // Assert + this._service.Verify(m => m.GetStorageDocumentMetadata(1, "", null, null), Times.Once()); + } + + #endregion + } +} diff --git a/source/backend/tests/unit/api/Services/DocumentFileServiceTest.cs b/source/backend/tests/unit/api/Services/DocumentFileServiceTest.cs index 2675db2d1c..7625f2aa26 100644 --- a/source/backend/tests/unit/api/Services/DocumentFileServiceTest.cs +++ b/source/backend/tests/unit/api/Services/DocumentFileServiceTest.cs @@ -93,6 +93,22 @@ public void GetPimsDocumentTypes_Research_Success() researchFileDocumentRepository.Verify(x => x.GetAllByResearchFile(It.IsAny()), Times.Once); } + [Fact] + public void GetPimsDocumentTypes_PropertyActivity_Success() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(Permissions.DocumentView, Permissions.ManagementView); + var propertyActivityFileDocumentRepository = this._helper.GetService>(); + + propertyActivityFileDocumentRepository.Setup(x => x.GetAllByPropertyActivity(It.IsAny())).Returns(new List()); + + // Act + var sut = service.GetFileDocuments(Constants.FileType.Management, 1); + + // Assert + propertyActivityFileDocumentRepository.Verify(x => x.GetAllByPropertyActivity(It.IsAny()), Times.Once); + } + [Fact] public void GetPimsDocumentTypes_Acquisition_Success() { @@ -141,6 +157,22 @@ public void GetAllDocuments_Lease_Success() leaseRepository.Verify(x => x.GetAllLeaseDocuments(It.IsAny()), Times.Once); } + [Fact] + public void GetAllDocuments_PropertyActivity_Success() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(Permissions.DocumentView, Permissions.ManagementView); + var propertyActivityDocumentRepository = this._helper.GetService>(); + + propertyActivityDocumentRepository.Setup(x => x.GetAllByPropertyActivity(It.IsAny())).Returns(new List()); + + // Act + var sut = service.GetFileDocuments(Constants.FileType.Management, 1); + + // Assert + propertyActivityDocumentRepository.Verify(x => x.GetAllByPropertyActivity(It.IsAny()), Times.Once); + } + [Fact] public void GetPimsDocumentTypes_Lease_NotAuthorized() { @@ -239,6 +271,23 @@ public void UploadDocumentAsync_Lease_ShouldThrowException_NotAuthorized() documentService.Verify(x => x.UploadDocumentAsync(It.IsAny()), Times.Never); } + [Fact] + public void UploadDocumentAsync_PropertyActivity_ShouldThrowException_NotAuthorized() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(); + var documentService = this._helper.GetService>(); + + DocumentUploadRequest uploadRequest = new() { DocumentTypeId = 1, File = this._helper.GetFormFile(string.Empty) }; + + // Assert + Func sut = async () => await service.UploadPropertyActivityDocumentAsync(1, uploadRequest); + + // Assert + sut.Should().Throw(); + documentService.Verify(x => x.UploadDocumentAsync(It.IsAny()), Times.Never); + } + [Fact] public async void UploadDocumentAsync_Project_Sucess() { @@ -371,6 +420,39 @@ public async void UploadDocumentAsync_Lease_Sucess() leaseRepository.Verify(x => x.AddLeaseDocument(It.IsAny())); } + [Fact] + public async void UploadDocumentAsync_PropertyActivity_Success() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(Permissions.DocumentAdd); + var documentService = this._helper.GetService>(); + var propertyActivityDocumentRepository = this._helper.GetService>(); + + documentService.Setup(x => x.UploadDocumentAsync(It.IsAny())) + .ReturnsAsync(new DocumentUploadResponse() + { + Document = new DocumentModel() + { + Id = 1, + }, + }); + + // Act + DocumentUploadRequest uploadRequest = new() + { + DocumentTypeMayanId = 3, + DocumentTypeId = 4, + File = this._helper.GetFormFile(string.Empty), + DocumentStatusCode = "DocumentStatus", + }; + + await service.UploadPropertyActivityDocumentAsync(1, uploadRequest); + + // Assert + documentService.Verify(x => x.UploadDocumentAsync(It.IsAny()), Times.Once); + propertyActivityDocumentRepository.Verify(x => x.AddPropertyActivityDocument(It.IsAny())); + } + [Fact] public void DeleteDocumentResearch_ShouldThrowException_NotAuthorized() { @@ -476,6 +558,62 @@ public async void DeleteDocumentResearch_Success_NoResults_Status_NotFound() researchDocumentRepository.Verify(x => x.DeleteResearch(It.IsAny()), Times.Once); } + [Fact] + public async void DeleteDocumentPropertyActivity_Success_NoResults_Status_NotFound() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(Permissions.DocumentDelete, Permissions.ManagementDelete); + var documentService = this._helper.GetService>(); + var propertyActivityDocumentRepository = this._helper.GetService>(); + + propertyActivityDocumentRepository.Setup(x => x.GetAllByPropertyActivity(It.IsAny())).Returns(new List()); + documentService.Setup(x => x.DeleteDocumentAsync(It.IsAny())) + .ReturnsAsync(new ExternalResult() + { + HttpStatusCode = System.Net.HttpStatusCode.NotFound, + }); + + PimsPropertyActivityDocument doc = new() + { + Internal_Id = 1, + DocumentId = 2, + }; + + // Act + await service.DeletePropertyActivityDocumentAsync(doc); + + // Assert + propertyActivityDocumentRepository.Verify(x => x.DeletePropertyActivityDocument(It.IsAny()), Times.Once); + } + + [Fact] + public async void Delete_PropertyActivity_Success_Status_Success() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(Permissions.DocumentDelete, Permissions.ManagementDelete); + var documentService = this._helper.GetService>(); + var documentRepository = this._helper.GetService>(); + + documentRepository.Setup(x => x.DocumentRelationshipCount(It.IsAny())).Returns(1); + documentService.Setup(x => x.DeleteDocumentAsync(It.IsAny())) + .ReturnsAsync(new ExternalResult() + { + Status = ExternalResultStatus.Success, + }); + + PimsPropertyActivityDocument doc = new() + { + Internal_Id = 1, + DocumentId = 2, + }; + + // Act + await service.DeletePropertyActivityDocumentAsync(doc); + + // Assert + documentService.Verify(x => x.DeleteDocumentAsync(It.IsAny()), Times.Once); + } + [Fact] public void DeleteDocumentAcquisition_ShouldThrowException_NotAuthorized() { @@ -497,6 +635,27 @@ public void DeleteDocumentAcquisition_ShouldThrowException_NotAuthorized() documentRepository.Verify(x => x.DeleteAcquisition(doc), Times.Never); } + [Fact] + public void DeletePropertyActivity_ShouldThrowException_NotAuthorized() + { + // Arrange + var service = this.CreateDocumentFileServiceWithPermissions(); + var documentRepository = this._helper.GetService>(); + + PimsPropertyActivityDocument doc = new() + { + Internal_Id = 1, + DocumentId = 2, + }; + + // Act + Func act = async () => await service.DeletePropertyActivityDocumentAsync(doc); + + // Assert + act.Should().Throw(); + documentRepository.Verify(x => x.DeletePropertyActivityDocument(doc), Times.Never); + } + [Fact] public async void DeleteDocumentAcquisition_Success_Status_Success() { diff --git a/source/backend/tests/unit/dal/Repositories/PropertyActivityDocumentRepositoryTest.cs b/source/backend/tests/unit/dal/Repositories/PropertyActivityDocumentRepositoryTest.cs new file mode 100644 index 0000000000..cf2f7ab287 --- /dev/null +++ b/source/backend/tests/unit/dal/Repositories/PropertyActivityDocumentRepositoryTest.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using FluentAssertions; +using Pims.Core.Test; +using Pims.Dal.Entities; +using Pims.Dal.Repositories; +using Pims.Dal.Security; +using Xunit; + +namespace Pims.Dal.Test.Repositories +{ + public class PropertyActivityDocumentRepositoryTest + { + [Fact] + public void AddPropertyActivity_Success() + { + // Arrange + var helper = new TestHelper(); + var user = PrincipalHelper.CreateForPermission(Permissions.DocumentView); + + var propertyActivityFileDocument = new PimsPropertyActivityDocument(); + + var repository = helper.CreateRepository(user); + + // Act + var result = repository.AddPropertyActivityDocument(propertyActivityFileDocument); + + // Assert + result.PropertyActivityDocumentId.Should().Be(1); + } + + [Fact] + public void GetAllByPropertyActivity_Success() + { + // Arrange + var helper = new TestHelper(); + var user = PrincipalHelper.CreateForPermission(Permissions.DocumentView); + + var document = new PimsDocument() { DocumentStatusTypeCodeNavigation = new PimsDocumentStatusType() { DocumentStatusTypeCode = "test" }, DocumentType = new PimsDocumentTyp() }; + var propertyActivityFileDocument = new PimsPropertyActivityDocument() { Document = document }; + PimsPropertyActivity pimsPropertyActivity = new PimsPropertyActivity() { PimsPropertyActivityDocuments = new List() { propertyActivityFileDocument } }; + var context = helper.CreatePimsContext(user, true).AddAndSaveChanges(pimsPropertyActivity); + + var repository = helper.CreateRepository(user); + + // Act + var result = repository.GetAllByPropertyActivity(propertyActivityFileDocument.PimsPropertyActivityId); + + // Assert + result.FirstOrDefault().Internal_Id.Should().Be(1); + } + + [Fact] + public void DeletePropertyActivity_Success() + { + // Arrange + var helper = new TestHelper(); + var user = PrincipalHelper.CreateForPermission(Permissions.DocumentView); + + var propertyActivityFileDocument = new PimsPropertyActivityDocument(); + + var repository = helper.CreateRepository(user); + + // Act + var result = repository.DeletePropertyActivityDocument(propertyActivityFileDocument); + + // Assert + result.Should().BeTrue(); + } + + [Fact] + public void DeletePropertyActivity_Null() + { + // Arrange + var helper = new TestHelper(); + var user = PrincipalHelper.CreateForPermission(Permissions.DocumentView); + + var repository = helper.CreateRepository(user); + + // Act + Action act = () => repository.DeletePropertyActivityDocument(null); + + // Assert + act.Should().Throw(); + } + } +} diff --git a/source/database/mssql/scripts/dbscripts/PSP_PIMS_LATEST/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql b/source/database/mssql/scripts/dbscripts/PSP_PIMS_LATEST/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql index 76fb564796..778f96e171 100644 --- a/source/database/mssql/scripts/dbscripts/PSP_PIMS_LATEST/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql +++ b/source/database/mssql/scripts/dbscripts/PSP_PIMS_LATEST/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql @@ -15,5 +15,6 @@ VALUES ('RESEARCH', 'Research file', 2), ('ACQUIRE', 'Acquisition file', 3), ('LEASLIC', 'Lease/License', 4), - ('DISPOSE', 'Disposition file', 5); + ('DISPOSE', 'Disposition file', 5), + ('MANAGEMENT', 'Management file', 6); GO diff --git a/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Alter Down/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql b/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Alter Down/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql new file mode 100644 index 0000000000..76fbd9f878 --- /dev/null +++ b/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Alter Down/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql @@ -0,0 +1,2 @@ +DELETE FROM PIMS_DOCUMENT_CATEGORY_SUBTYPE WHERE DOCUMENT_CATEGORY_TYPE_CODE = 'MANAGEMENT'; +DELETE FROM PIMS_DOCUMENT_CATEGORY_TYPE WHERE DOCUMENT_CATEGORY_TYPE_CODE = 'MANAGEMENT'; diff --git a/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Alter Up/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql b/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Alter Up/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql new file mode 100644 index 0000000000..1f3e465f9b --- /dev/null +++ b/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Alter Up/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql @@ -0,0 +1,4 @@ +INSERT INTO PIMS_DOCUMENT_CATEGORY_TYPE (DOCUMENT_CATEGORY_TYPE_CODE, DESCRIPTION, DISPLAY_ORDER) +VALUES + ('MANAGEMENT', 'Management', 6); +GO diff --git a/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql b/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql index 76fb564796..778f96e171 100644 --- a/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql +++ b/source/database/mssql/scripts/dbscripts/PSP_PIMS_S66_00/Build/129_DML_PIMS_DOCUMENT_CATEGORY_TYPE.sql @@ -15,5 +15,6 @@ VALUES ('RESEARCH', 'Research file', 2), ('ACQUIRE', 'Acquisition file', 3), ('LEASLIC', 'Lease/License', 4), - ('DISPOSE', 'Disposition file', 5); + ('DISPOSE', 'Disposition file', 5), + ('MANAGEMENT', 'Management file', 6); GO diff --git a/source/frontend/src/AppRouter.tsx b/source/frontend/src/AppRouter.tsx index b4efb5b704..61b00e46ce 100644 --- a/source/frontend/src/AppRouter.tsx +++ b/source/frontend/src/AppRouter.tsx @@ -23,7 +23,6 @@ import useKeycloakWrapper from '@/hooks/useKeycloakWrapper'; import AuthLayout from '@/layouts/AuthLayout'; import PublicLayout from '@/layouts/PublicLayout'; import { NotFoundPage } from '@/pages/404/NotFoundPage'; -import { TestFileManagement } from '@/pages/TestFileManagement'; import AppRoute from '@/utils/AppRoute'; import componentLoader from '@/utils/utils'; @@ -284,13 +283,6 @@ const AppRouter: React.FC> = () => { claim={Claims.ADMIN_USERS} title={getTitle('Edit User')} /> - } /> diff --git a/source/frontend/src/constants/documentRelationshipType.ts b/source/frontend/src/constants/documentRelationshipType.ts index 6d2ea83ebb..78ffcf4bab 100644 --- a/source/frontend/src/constants/documentRelationshipType.ts +++ b/source/frontend/src/constants/documentRelationshipType.ts @@ -4,4 +4,5 @@ export enum DocumentRelationshipType { TEMPLATES = 'templates', LEASES = 'leases', PROJECTS = 'projects', + MANAGEMENT_FILES = 'managementFiles', } diff --git a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/activity/detail/PropertyActivityDetailView.tsx b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/activity/detail/PropertyActivityDetailView.tsx index 3c9c110fdf..fe96fb4dd9 100644 --- a/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/activity/detail/PropertyActivityDetailView.tsx +++ b/source/frontend/src/features/mapSideBar/property/tabs/propertyDetailsManagement/activity/detail/PropertyActivityDetailView.tsx @@ -12,7 +12,9 @@ import { Section } from '@/components/common/Section/Section'; import { SectionField } from '@/components/common/Section/SectionField'; import { StyledEditWrapper, StyledSummarySection } from '@/components/common/Section/SectionStyles'; import * as Styled from '@/components/common/styles'; +import { DocumentRelationshipType } from '@/constants/documentRelationshipType'; import { Claims } from '@/constants/index'; +import DocumentListContainer from '@/features/documents/list/DocumentListContainer'; import useKeycloakWrapper from '@/hooks/useKeycloakWrapper'; import { Api_PropertyActivity, Api_PropertyActivityInvoice } from '@/models/api/PropertyActivity'; import { formatMoney, prettyFormatDate } from '@/utils'; @@ -146,6 +148,12 @@ export const PropertyActivityDetailView: React.FunctionComponent< + + diff --git a/source/frontend/src/pages/TestFileManagement.tsx b/source/frontend/src/pages/TestFileManagement.tsx deleted file mode 100644 index 2d29784a53..0000000000 --- a/source/frontend/src/pages/TestFileManagement.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Col, Row } from 'react-bootstrap'; -import styled from 'styled-components'; - -import { DocumentRelationshipType } from '@/constants/documentRelationshipType'; -import DocumentListContainer from '@/features/documents/list/DocumentListContainer'; - -export const TestFileManagement: React.FunctionComponent> = () => { - return ( - - - -

File Management test page

- -
- - - - - -
- ); -}; - -const StyledBody = styled.div` - padding: 10rem; - width: 100%; - position: relative; - overflow: auto; -`;