Implemented image storing to S3 while reporting task
This commit is contained in:
parent
d5e7d38101
commit
abe7870ad5
@ -44,6 +44,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
public DbSet<TaskAllocation> TaskAllocations { get; set; }
|
public DbSet<TaskAllocation> TaskAllocations { get; set; }
|
||||||
public DbSet<TaskComment> TaskComments { get; set; }
|
public DbSet<TaskComment> TaskComments { get; set; }
|
||||||
public DbSet<TaskMembers> TaskMembers { get; set; }
|
public DbSet<TaskMembers> TaskMembers { get; set; }
|
||||||
|
public DbSet<TaskAttachment> TaskAttachments { get; set; }
|
||||||
public DbSet<Attendance> Attendes { get; set; }
|
public DbSet<Attendance> Attendes { get; set; }
|
||||||
public DbSet<AttendanceLog> AttendanceLogs { get; set; }
|
public DbSet<AttendanceLog> AttendanceLogs { get; set; }
|
||||||
public DbSet<Employee> Employees { get; set; }
|
public DbSet<Employee> Employees { get; set; }
|
||||||
|
3269
Marco.Pms.DataAccess/Migrations/20250612094243_Added_TaskAttachments_Table.Designer.cs
generated
Normal file
3269
Marco.Pms.DataAccess/Migrations/20250612094243_Added_TaskAttachments_Table.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_TaskAttachments_Table : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "TaskAttachments",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
ReferenceId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
DocumentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_TaskAttachments", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "TaskAttachments");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,23 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
b.ToTable("TaskAllocations");
|
b.ToTable("TaskAllocations");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.Activities.TaskAttachment", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid>("DocumentId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid>("ReferenceId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("TaskAttachments");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b =>
|
modelBuilder.Entity("Marco.Pms.Model.Activities.TaskComment", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
9
Marco.Pms.Model/Activities/TaskAttachment.cs
Normal file
9
Marco.Pms.Model/Activities/TaskAttachment.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.Activities
|
||||||
|
{
|
||||||
|
public class TaskAttachment
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Guid ReferenceId { get; set; }
|
||||||
|
public Guid DocumentId { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
|
||||||
|
|
||||||
namespace Marco.Pms.Model.Activities
|
|
||||||
{
|
|
||||||
public class TaskImages
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
public Guid TaskAllocationId { get; set; }
|
|
||||||
[ValidateNever]
|
|
||||||
[ForeignKey(nameof(TaskAllocationId))]
|
|
||||||
public TaskAllocation? TaskAllocation { get; set; }
|
|
||||||
|
|
||||||
public string? ImagePath { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,6 @@
|
|||||||
namespace Marco.Pms.Model.Dtos.Activities
|
using Marco.Pms.Model.Utilities;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Dtos.Activities
|
||||||
{
|
{
|
||||||
public class ReportTaskDto
|
public class ReportTaskDto
|
||||||
{
|
{
|
||||||
@ -7,5 +9,6 @@
|
|||||||
public DateTime ReportedDate { get; set; }
|
public DateTime ReportedDate { get; set; }
|
||||||
public string? Comment { get; set; }
|
public string? Comment { get; set; }
|
||||||
public List<ReportCheckListDto>? CheckList { get; set; }
|
public List<ReportCheckListDto>? CheckList { get; set; }
|
||||||
|
public List<FileUploadModel>? Images { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
public List<UpdateContactPhoneDto>? ContactPhones { get; set; }
|
public List<UpdateContactPhoneDto>? ContactPhones { get; set; }
|
||||||
public List<UpdateContactEmailDto>? ContactEmails { get; set; }
|
public List<UpdateContactEmailDto>? ContactEmails { get; set; }
|
||||||
public List<Guid>? BucketIds { get; set; }
|
public List<Guid>? BucketIds { get; set; }
|
||||||
public Guid ContactCategoryId { get; set; }
|
public Guid? ContactCategoryId { get; set; }
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public string? Organization { get; set; }
|
public string? Organization { get; set; }
|
||||||
public string? Address { get; set; }
|
public string? Address { get; set; }
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public Guid AssignedBy { get; set; }
|
public Guid AssignedBy { get; set; }
|
||||||
public Guid WorkItemId { get; set; }
|
public Guid WorkItemId { get; set; }
|
||||||
|
|
||||||
public List<CommentVM>? Comments { get; set; }
|
public List<CommentVM>? Comments { get; set; }
|
||||||
public List<CheckListVM>? checkList { get; set; }
|
public List<CheckListVM>? checkList { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace Marco.Pms.Model.ViewModels.Activities
|
|||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
public string? AssignBy { get; set; }
|
public string? AssignBy { get; set; }
|
||||||
public WorkItem? WorkItem { get; set; }
|
public WorkItem? WorkItem { get; set; }
|
||||||
|
List<string>? preSignedUrls { get; set; }
|
||||||
public List<CommentVM>? Comments { get; set; }
|
public List<CommentVM>? Comments { get; set; }
|
||||||
public List<EmployeeVM>? TeamMembers { get; set; }
|
public List<EmployeeVM>? TeamMembers { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -688,7 +688,6 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
Document? document = null;
|
Document? document = null;
|
||||||
var Image = recordAttendanceDot.Image;
|
var Image = recordAttendanceDot.Image;
|
||||||
var objectKey = string.Empty;
|
|
||||||
var preSignedUrl = string.Empty;
|
var preSignedUrl = string.Empty;
|
||||||
|
|
||||||
if (Image != null && Image.ContentType != null)
|
if (Image != null && Image.ContentType != null)
|
||||||
@ -697,7 +696,16 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
if (string.IsNullOrEmpty(Image.Base64Data))
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
|
|
||||||
objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, TenantId, "attendance");
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, TenantId, "attendance");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{TenantId}/Employee/{recordAttendanceDot.EmployeeID}/Attendance/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey);
|
preSignedUrl = _s3Service.GeneratePreSignedUrlAsync(objectKey);
|
||||||
|
|
||||||
document = new Document
|
document = new Document
|
||||||
|
@ -68,7 +68,16 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "forum");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{tenantId}/project-{createTicketDto.LinkedProjectId}/froum/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
|
|
||||||
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, createTicketDto.CreatedAt, tenantId);
|
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, createTicketDto.CreatedAt, tenantId);
|
||||||
_context.Documents.Add(document);
|
_context.Documents.Add(document);
|
||||||
@ -182,7 +191,16 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "forum");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{tenantId}/project-{updateTicketDto.LinkedProjectId}/froum/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
|
|
||||||
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, updateTicketDto.CreatedAt, tenantId);
|
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, updateTicketDto.CreatedAt, tenantId);
|
||||||
_context.Documents.Add(document);
|
_context.Documents.Add(document);
|
||||||
@ -329,6 +347,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
||||||
List<Document> documents = new List<Document>();
|
List<Document> documents = new List<Document>();
|
||||||
|
|
||||||
|
TicketForum? ticket = await _context.Tickets.FirstOrDefaultAsync(t => t.Id == addCommentDto.TicketId);
|
||||||
|
|
||||||
|
if (ticket == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Ticket {TicketId} not Found in database", addCommentDto.TicketId);
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
|
}
|
||||||
|
|
||||||
TicketComment comment = addCommentDto.ToTicketCommentFromAddCommentDto(tenantId);
|
TicketComment comment = addCommentDto.ToTicketCommentFromAddCommentDto(tenantId);
|
||||||
_context.TicketComments.Add(comment);
|
_context.TicketComments.Add(comment);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
@ -344,7 +370,16 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "forum");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{tenantId}/project-{ticket.LinkedProjectId}/froum/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
|
|
||||||
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, addCommentDto.SentAt, tenantId);
|
Document document = attachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, addCommentDto.SentAt, tenantId);
|
||||||
_context.Documents.Add(document);
|
_context.Documents.Add(document);
|
||||||
@ -396,6 +431,14 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
Guid tenantId = _userHelper.GetTenantId();
|
Guid tenantId = _userHelper.GetTenantId();
|
||||||
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
List<TicketAttachment> attachments = new List<TicketAttachment>();
|
||||||
|
|
||||||
|
TicketForum? ticket = await _context.Tickets.FirstOrDefaultAsync(t => t.Id == updateCommentDto.TicketId);
|
||||||
|
|
||||||
|
if (ticket == null)
|
||||||
|
{
|
||||||
|
_logger.LogError("Ticket {TicketId} not Found in database", updateCommentDto.TicketId);
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
|
}
|
||||||
|
|
||||||
TicketComment existingComment = await _context.TicketComments.AsNoTracking().FirstOrDefaultAsync(c => c.Id == updateCommentDto.Id) ?? new TicketComment();
|
TicketComment existingComment = await _context.TicketComments.AsNoTracking().FirstOrDefaultAsync(c => c.Id == updateCommentDto.Id) ?? new TicketComment();
|
||||||
TicketComment updateComment = updateCommentDto.ToTicketCommentFromUpdateCommentDto(tenantId, existingComment);
|
TicketComment updateComment = updateCommentDto.ToTicketCommentFromUpdateCommentDto(tenantId, existingComment);
|
||||||
_context.TicketComments.Update(updateComment);
|
_context.TicketComments.Update(updateComment);
|
||||||
@ -419,7 +462,16 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
}
|
}
|
||||||
|
|
||||||
var objectKey = await _s3Service.UploadFileAsync(Image.Base64Data, tenantId, "forum");
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "forum");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{tenantId}/project-{ticket.LinkedProjectId}/froum/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
|
|
||||||
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, existingComment.SentAt, tenantId);
|
Document document = attachmentDto.ToDocumentFromUpdateAttachmentDto(objectKey, objectKey, existingComment.SentAt, tenantId);
|
||||||
_context.Documents.Add(document);
|
_context.Documents.Add(document);
|
||||||
@ -491,6 +543,16 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
Guid tenantId = _userHelper.GetTenantId();
|
Guid tenantId = _userHelper.GetTenantId();
|
||||||
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
List<TicketAttachmentVM> ticketAttachmentVMs = new List<TicketAttachmentVM>();
|
||||||
|
|
||||||
|
List<Guid> ticketIds = forumAttachmentDtos.Select(f => f.TicketId.HasValue ? f.TicketId.Value : Guid.Empty).ToList();
|
||||||
|
|
||||||
|
List<TicketForum> tickets = await _context.Tickets.Where(t => ticketIds.Contains(t.Id)).ToListAsync();
|
||||||
|
|
||||||
|
if (tickets == null || tickets.Count > 0)
|
||||||
|
{
|
||||||
|
_logger.LogError("Tickets not Found in database");
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Ticket not Found", "Ticket not Found", 404));
|
||||||
|
}
|
||||||
|
|
||||||
TicketAttachment attachment = new TicketAttachment();
|
TicketAttachment attachment = new TicketAttachment();
|
||||||
|
|
||||||
foreach (var forumAttachmentDto in forumAttachmentDtos)
|
foreach (var forumAttachmentDto in forumAttachmentDtos)
|
||||||
@ -505,7 +567,17 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_logger.LogError("ticket ID is missing");
|
_logger.LogError("ticket ID is missing");
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("ticket ID is missing", "ticket ID is missing", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("ticket ID is missing", "ticket ID is missing", 400));
|
||||||
}
|
}
|
||||||
var objectKey = await _s3Service.UploadFileAsync(forumAttachmentDto.Base64Data, tenantId, "forum");
|
var ticket = tickets.FirstOrDefault(t => t.Id == forumAttachmentDto.TicketId);
|
||||||
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = forumAttachmentDto.Base64Data.Contains(",")
|
||||||
|
? forumAttachmentDto.Base64Data.Substring(forumAttachmentDto.Base64Data.IndexOf(",") + 1)
|
||||||
|
: forumAttachmentDto.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "forum");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{tenantId}/project-{ticket?.LinkedProjectId}/froum/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
|
|
||||||
Document document = forumAttachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, forumAttachmentDto.SentAt, tenantId);
|
Document document = forumAttachmentDto.ToDocumentFromForumAttachmentDto(objectKey, objectKey, forumAttachmentDto.SentAt, tenantId);
|
||||||
_context.Documents.Add(document);
|
_context.Documents.Add(document);
|
||||||
|
@ -749,11 +749,11 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
return Ok(response);
|
return Ok(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("contact-tag/{id}")]
|
//[HttpGet("contact-tag/{id}")]
|
||||||
public async Task<IActionResult> GetContactTagMaster(Guid id)
|
//public async Task<IActionResult> GetContactTagMaster(Guid id)
|
||||||
{
|
//{
|
||||||
return Ok();
|
// return Ok();
|
||||||
}
|
//}
|
||||||
|
|
||||||
[HttpPost("contact-tag")]
|
[HttpPost("contact-tag")]
|
||||||
public async Task<IActionResult> CreateContactTagMaster([FromBody] CreateContactTagDto contactTagDto)
|
public async Task<IActionResult> CreateContactTagMaster([FromBody] CreateContactTagDto contactTagDto)
|
||||||
|
@ -8,10 +8,13 @@ using Marco.Pms.Model.Projects;
|
|||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Marco.Pms.Model.ViewModels.Activities;
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
using Marco.Pms.Model.ViewModels.Employee;
|
using Marco.Pms.Model.ViewModels.Employee;
|
||||||
|
using Marco.Pms.Services.Service;
|
||||||
using MarcoBMS.Services.Helpers;
|
using MarcoBMS.Services.Helpers;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Document = Marco.Pms.Model.DocumentManager.Document;
|
||||||
|
|
||||||
namespace MarcoBMS.Services.Controllers
|
namespace MarcoBMS.Services.Controllers
|
||||||
{
|
{
|
||||||
@ -23,12 +26,14 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
{
|
{
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
private readonly UserHelper _userHelper;
|
private readonly UserHelper _userHelper;
|
||||||
|
private readonly S3UploadService _s3Service;
|
||||||
|
|
||||||
|
|
||||||
public TaskController(ApplicationDbContext context, UserHelper userHelper)
|
public TaskController(ApplicationDbContext context, UserHelper userHelper, S3UploadService s3Service)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_userHelper = userHelper;
|
_userHelper = userHelper;
|
||||||
|
_s3Service = s3Service;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Guid GetTenantId()
|
private Guid GetTenantId()
|
||||||
@ -84,7 +89,6 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Task assignned successfully", 200));
|
return Ok(ApiResponse<object>.SuccessResponse(response, "Task assignned successfully", 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost("report")]
|
[HttpPost("report")]
|
||||||
public async Task<IActionResult> ReportTaskProgress([FromBody] ReportTaskDto reportTask)
|
public async Task<IActionResult> ReportTaskProgress([FromBody] ReportTaskDto reportTask)
|
||||||
{
|
{
|
||||||
@ -104,10 +108,13 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
var checkListIds = reportTask.CheckList != null ? reportTask.CheckList.Select(c => c.Id).ToList() : new List<Guid>();
|
var checkListIds = reportTask.CheckList != null ? reportTask.CheckList.Select(c => c.Id).ToList() : new List<Guid>();
|
||||||
var checkList = await _context.ActivityCheckLists.Where(c => checkListIds.Contains(c.Id)).ToListAsync();
|
var checkList = await _context.ActivityCheckLists.Where(c => checkListIds.Contains(c.Id)).ToListAsync();
|
||||||
if (taskAllocation == null)
|
if (taskAllocation == null || taskAllocation.WorkItem == null)
|
||||||
{
|
{
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("No such task has been allocated.", "No such task has been allocated.", 400));
|
return BadRequest(ApiResponse<object>.ErrorResponse("No such task has been allocated.", "No such task has been allocated.", 400));
|
||||||
}
|
}
|
||||||
|
WorkArea workArea = await _context.WorkAreas.Include(a => a.Floor).FirstOrDefaultAsync(a => a.Id == taskAllocation.WorkItem.WorkAreaId) ?? new WorkArea();
|
||||||
|
|
||||||
|
var bulding = await _context.Buildings.FirstOrDefaultAsync(b => b.Id == (workArea.Floor != null ? workArea.Floor.BuildingId : Guid.Empty));
|
||||||
if (taskAllocation.WorkItem != null)
|
if (taskAllocation.WorkItem != null)
|
||||||
{
|
{
|
||||||
if (taskAllocation.CompletedTask != 0)
|
if (taskAllocation.CompletedTask != 0)
|
||||||
@ -143,6 +150,49 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
_context.CheckListMappings.AddRange(checkListMappings);
|
_context.CheckListMappings.AddRange(checkListMappings);
|
||||||
var comment = reportTask.ToCommentFromReportTaskDto(tenantId, Employee.Id);
|
var comment = reportTask.ToCommentFromReportTaskDto(tenantId, Employee.Id);
|
||||||
|
|
||||||
|
var Images = reportTask.Images;
|
||||||
|
|
||||||
|
if (Images != null && Images.Count > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (var Image in Images)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(Image.Base64Data))
|
||||||
|
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
|
||||||
|
|
||||||
|
//If base64 has a data URI prefix, strip it
|
||||||
|
var base64 = Image.Base64Data.Contains(",")
|
||||||
|
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
|
||||||
|
: Image.Base64Data;
|
||||||
|
|
||||||
|
string fileType = _s3Service.GetContentTypeFromBase64(base64);
|
||||||
|
string fileName = _s3Service.GenerateFileName(fileType, tenantId, "task_report");
|
||||||
|
|
||||||
|
string objectKey = $"tenant-{tenantId}/project-{bulding?.ProjectId}/Actitvity/{fileName}";
|
||||||
|
await _s3Service.UploadFileAsync(base64, fileType, objectKey);
|
||||||
|
|
||||||
|
Document document = new Document
|
||||||
|
{
|
||||||
|
FileName = Image.FileName ?? "",
|
||||||
|
ContentType = Image.ContentType ?? "",
|
||||||
|
S3Key = objectKey,
|
||||||
|
Base64Data = Image.Base64Data,
|
||||||
|
FileSize = Image.FileSize,
|
||||||
|
UploadedAt = DateTime.UtcNow,
|
||||||
|
TenantId = tenantId
|
||||||
|
};
|
||||||
|
_context.Documents.Add(document);
|
||||||
|
TaskAttachment attachment = new TaskAttachment
|
||||||
|
{
|
||||||
|
DocumentId = document.Id,
|
||||||
|
ReferenceId = reportTask.Id
|
||||||
|
};
|
||||||
|
_context.TaskAttachments.Add(attachment);
|
||||||
|
}
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
_context.TaskComments.Add(comment);
|
_context.TaskComments.Add(comment);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
|
@ -28,53 +28,46 @@ namespace Marco.Pms.Services.Service
|
|||||||
_s3Client = new AmazonS3Client(settings.AccessKey, settings.SecretKey, region);
|
_s3Client = new AmazonS3Client(settings.AccessKey, settings.SecretKey, region);
|
||||||
}
|
}
|
||||||
//public async Task<string> UploadFileAsync(string fileName, string contentType)
|
//public async Task<string> UploadFileAsync(string fileName, string contentType)
|
||||||
public async Task<string> UploadFileAsync(string base64Data, Guid tenantId, string tag)
|
public async Task UploadFileAsync(string base64, string fileType, string objectKey)
|
||||||
{
|
{
|
||||||
byte[] fileBytes;
|
byte[] fileBytes;
|
||||||
|
|
||||||
//If base64 has a data URI prefix, strip it
|
|
||||||
var base64 = base64Data.Contains(",")
|
|
||||||
? base64Data.Substring(base64Data.IndexOf(",") + 1)
|
|
||||||
: base64Data;
|
|
||||||
var allowedFilesType = _configuration.GetSection("WhiteList:ContentType")
|
var allowedFilesType = _configuration.GetSection("WhiteList:ContentType")
|
||||||
.GetChildren()
|
.GetChildren()
|
||||||
.Select(x => x.Value)
|
.Select(x => x.Value)
|
||||||
.ToList();
|
.ToList();
|
||||||
string fileType = GetContentTypeFromBase64(base64);
|
|
||||||
if (allowedFilesType != null && allowedFilesType.Contains(fileType))
|
if (allowedFilesType == null || !allowedFilesType.Contains(fileType))
|
||||||
{
|
{
|
||||||
string fileName = GenerateFileName(fileType, tenantId, tag);
|
throw new InvalidOperationException("Unsupported file type.");
|
||||||
|
|
||||||
fileBytes = Convert.FromBase64String(base64);
|
|
||||||
|
|
||||||
|
|
||||||
using var fileStream = new MemoryStream(fileBytes);
|
|
||||||
|
|
||||||
// Generate a unique object key (you can customize this)
|
|
||||||
var objectKey = $"{fileName}";
|
|
||||||
|
|
||||||
var uploadRequest = new TransferUtilityUploadRequest
|
|
||||||
{
|
|
||||||
InputStream = fileStream,
|
|
||||||
Key = objectKey,
|
|
||||||
BucketName = _bucketName,
|
|
||||||
ContentType = fileType,
|
|
||||||
AutoCloseStream = true
|
|
||||||
};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var transferUtility = new TransferUtility(_s3Client);
|
|
||||||
await transferUtility.UploadAsync(uploadRequest);
|
|
||||||
_logger.LogInfo("File uploaded to Amazon S3");
|
|
||||||
return objectKey;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError("{error} while uploading file to S3", ex.Message);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
throw new InvalidOperationException("Unsupported file type.");
|
|
||||||
|
fileBytes = Convert.FromBase64String(base64);
|
||||||
|
|
||||||
|
|
||||||
|
using var fileStream = new MemoryStream(fileBytes);
|
||||||
|
|
||||||
|
var uploadRequest = new TransferUtilityUploadRequest
|
||||||
|
{
|
||||||
|
InputStream = fileStream,
|
||||||
|
Key = objectKey,
|
||||||
|
BucketName = _bucketName,
|
||||||
|
ContentType = fileType,
|
||||||
|
AutoCloseStream = true
|
||||||
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var transferUtility = new TransferUtility(_s3Client);
|
||||||
|
await transferUtility.UploadAsync(uploadRequest);
|
||||||
|
_logger.LogInfo("File uploaded to Amazon S3");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError("{error} while uploading file to S3", ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public string GeneratePreSignedUrlAsync(string objectKey)
|
public string GeneratePreSignedUrlAsync(string objectKey)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user