push only for upload attachment and project code but not working the autocomplete yet
This commit is contained in:
parent
0612679648
commit
6e0551707e
@ -22,6 +22,8 @@ namespace CPRNIMS.Domain.Contracts.Items
|
|||||||
Task<List<ItemColor>> GetItemColor(ItemDto itemDto);
|
Task<List<ItemColor>> GetItemColor(ItemDto itemDto);
|
||||||
Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto);
|
Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto);
|
||||||
Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto);
|
Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto);
|
||||||
|
Task<List<ProjectCodes>> GetProjectCode();
|
||||||
|
Task<List<ProjectCodes>> GetProjectCodeByTerm(string? fileName);
|
||||||
Task<(long, long)> GetPRNo();
|
Task<(long, long)> GetPRNo();
|
||||||
Task<ResponseObject> PostPurchRequest(ItemDto itemDto);
|
Task<ResponseObject> PostPurchRequest(ItemDto itemDto);
|
||||||
Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto);
|
Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto);
|
||||||
|
|||||||
@ -268,7 +268,7 @@ namespace CPRNIMS.Domain.Services.Items
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
existing.OrigFileName = attach.OrigFileName;
|
existing.OrigFileName = attach.OrigFileName;
|
||||||
existing.FileName = Guid.NewGuid().ToString();
|
existing.FileName = attach.FileName;
|
||||||
}
|
}
|
||||||
await _dbContext.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
@ -316,5 +316,19 @@ namespace CPRNIMS.Domain.Services.Items
|
|||||||
|
|
||||||
return allItems ?? new List<NotifUserKey>();
|
return allItems ?? new List<NotifUserKey>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<ProjectCodes>> GetProjectCode()
|
||||||
|
{
|
||||||
|
return await _dbContext.ProjectCodes
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
public async Task<List<ProjectCodes>> GetProjectCodeByTerm(string? term)
|
||||||
|
{
|
||||||
|
return await _dbContext.ProjectCodes
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(p => EF.Functions.Like(p.ProjectCode, $"%{term}%"))
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ namespace CPRNIMS.Domain.UIContracts.Items
|
|||||||
Task<List<ItemVM>> GetItemUOM(User user, ItemVM viewModel);
|
Task<List<ItemVM>> GetItemUOM(User user, ItemVM viewModel);
|
||||||
Task<List<ItemVM>> GetDepartment(User user, ItemVM viewModel);
|
Task<List<ItemVM>> GetDepartment(User user, ItemVM viewModel);
|
||||||
Task<List<ItemVM>> GetItemCart(User user, ItemVM viewModel);
|
Task<List<ItemVM>> GetItemCart(User user, ItemVM viewModel);
|
||||||
|
Task<List<ItemVM>?> GetProjectCode(User user, ItemVM viewModels);
|
||||||
Task<ItemVM> PostPurchRequest(User user, ItemVM viewModel);
|
Task<ItemVM> PostPurchRequest(User user, ItemVM viewModel);
|
||||||
Task<ItemVM> PostPutItem(User user, ItemVM viewModel);
|
Task<ItemVM> PostPutItem(User user, ItemVM viewModel);
|
||||||
Task<ItemVM> PutItemDetail(User user, ItemVM viewModel);
|
Task<ItemVM> PutItemDetail(User user, ItemVM viewModel);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ namespace CPRNIMS.Domain.UIContracts.PR
|
|||||||
Task<PRVM> PRItemRemoval(User user, PRVM viewModel);
|
Task<PRVM> PRItemRemoval(User user, PRVM viewModel);
|
||||||
Task<PRVM> ApprovedSelectedPRItem(User user, PRVM viewModel);
|
Task<PRVM> ApprovedSelectedPRItem(User user, PRVM viewModel);
|
||||||
Task<PRVM> PostPutProjectCode(User user, PRVM viewModel);
|
Task<PRVM> PostPutProjectCode(User user, PRVM viewModel);
|
||||||
|
Task<PRVM> PostPutAttachment(User user, PRVM prVM);
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -129,6 +129,11 @@ namespace CPRNIMS.Domain.UIServices.Items
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region Get Method
|
#region Get Method
|
||||||
|
public async Task<List<ItemVM>> GetProjectCode(Infrastructure.Models.Account.User user, ItemVM viewModel)
|
||||||
|
{
|
||||||
|
return await SendGetApiRequest(user, viewModel,
|
||||||
|
_configuration["LLI:NonInvent:ItemMgmt:GetProjectCode"]);
|
||||||
|
}
|
||||||
public async Task<List<ItemVM>> GetItemDetail(Infrastructure.Models.Account.User user,
|
public async Task<List<ItemVM>> GetItemDetail(Infrastructure.Models.Account.User user,
|
||||||
ItemVM viewModel)
|
ItemVM viewModel)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -264,6 +264,12 @@ namespace CPRNIMS.Domain.UIServices.PR
|
|||||||
return await SendPostApiRequest(user, viewModel,
|
return await SendPostApiRequest(user, viewModel,
|
||||||
_configuration["LLI:NonInvent:PRMgmt:PostPutProjectCode"]);
|
_configuration["LLI:NonInvent:PRMgmt:PostPutProjectCode"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<PRVM> PostPutAttachment(User user, PRVM prVM)
|
||||||
|
{
|
||||||
|
return await SendPostApiRequest(user, prVM,
|
||||||
|
_configuration["LLI:NonInvent:PRMgmt:PostPutAttachment"]);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,6 +12,7 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
|
|||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public long PRDetailsId { get; set; }
|
public long PRDetailsId { get; set; }
|
||||||
|
public long PRId { get; set; }
|
||||||
public long ItemCodeId { get; set; }
|
public long ItemCodeId { get; set; }
|
||||||
public short ItemClassId { get; set; }
|
public short ItemClassId { get; set; }
|
||||||
public string? Department { get; set; }
|
public string? Department { get; set; }
|
||||||
@ -38,5 +39,7 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
|
|||||||
public string? AttestedBy { get; set; }
|
public string? AttestedBy { get; set; }
|
||||||
public string? ApprovedBy { get; set; }
|
public string? ApprovedBy { get; set; }
|
||||||
public string? ProjectCode { get; set; }
|
public string? ProjectCode { get; set; }
|
||||||
|
public string? FileName { get; set; }
|
||||||
|
public string? OrigFileName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,9 +32,9 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
|
|||||||
public string? UOMName { get; set; }
|
public string? UOMName { get; set; }
|
||||||
public string? ItemColorName { get; set; }
|
public string? ItemColorName { get; set; }
|
||||||
public long PRNo { get; set; }
|
public long PRNo { get; set; }
|
||||||
|
public long PRId { get; set; }
|
||||||
public string? Remarks { get; set; }
|
public string? Remarks { get; set; }
|
||||||
public DateTime DateNeeded { get; set; }
|
public DateTime DateNeeded { get; set; }
|
||||||
//public bool Queue { get; set; }
|
|
||||||
public string? AggreItemName { get; set; }
|
public string? AggreItemName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
using CPRNIMS.Domain.Contracts.Items;
|
using CPRNIMS.Domain.Contracts.Items;
|
||||||
using CPRNIMS.Domain.Contracts.SMTP;
|
|
||||||
using CPRNIMS.Domain.Services;
|
using CPRNIMS.Domain.Services;
|
||||||
using CPRNIMS.Infrastructure.Dto.Items;
|
using CPRNIMS.Infrastructure.Dto.Items;
|
||||||
using CPRNIMS.Infrastructure.Entities.Items;
|
|
||||||
using CPRNIMS.Infrastructure.Helper;
|
using CPRNIMS.Infrastructure.Helper;
|
||||||
using CPRNIMS.Infrastructure.Models.Common;
|
using CPRNIMS.Infrastructure.Models.Common;
|
||||||
using CPRNIMS.Infrastructure.ViewModel.Common;
|
using CPRNIMS.Infrastructure.ViewModel.Common;
|
||||||
using CPRNIMS.Infrastructure.ViewModel.Items;
|
using CPRNIMS.Infrastructure.ViewModel.Items;
|
||||||
using CPRNIMS.WebApi.Controllers.Base;
|
using CPRNIMS.WebApi.Controllers.Base;
|
||||||
|
using Google.Apis.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@ -172,6 +171,12 @@ namespace CPRNIMS.WebApi.Controllers.Items
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[HttpPost("GetProjectCode")]
|
||||||
|
public async Task<IActionResult> GetProjectCode(ItemCodeDto itemDto)
|
||||||
|
{
|
||||||
|
var results = await _item.GetProjectCodeByTerm(itemDto.FileName);
|
||||||
|
return Ok( new {message="success", messCode=1, data= results });
|
||||||
|
}
|
||||||
|
|
||||||
[HttpPost("GetDepartment")]
|
[HttpPost("GetDepartment")]
|
||||||
public async Task<IActionResult> GetDepartment(ItemCodeDto itemDto)
|
public async Task<IActionResult> GetDepartment(ItemCodeDto itemDto)
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using CPRNIMS.Domain.Contracts.PR;
|
using CPRNIMS.Domain.Contracts.Items;
|
||||||
|
using CPRNIMS.Domain.Contracts.PR;
|
||||||
using CPRNIMS.Domain.Services;
|
using CPRNIMS.Domain.Services;
|
||||||
|
using CPRNIMS.Infrastructure.Dto.Items;
|
||||||
using CPRNIMS.Infrastructure.Dto.PO;
|
using CPRNIMS.Infrastructure.Dto.PO;
|
||||||
using CPRNIMS.Infrastructure.Dto.PR;
|
using CPRNIMS.Infrastructure.Dto.PR;
|
||||||
using CPRNIMS.Infrastructure.Entities.PO;
|
using CPRNIMS.Infrastructure.Entities.PO;
|
||||||
@ -12,6 +14,7 @@ using CPRNIMS.WebApi.Controllers.Base;
|
|||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.HttpResults;
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Reflection.Metadata.Ecma335;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
|
||||||
@ -23,17 +26,30 @@ namespace CPRNIMS.WebApi.Controllers.PR
|
|||||||
private readonly IPRequest _pRequest;
|
private readonly IPRequest _pRequest;
|
||||||
private readonly SMTPHelper _smptHelper;
|
private readonly SMTPHelper _smptHelper;
|
||||||
private readonly IConfiguration _config;
|
private readonly IConfiguration _config;
|
||||||
|
private readonly IItem _item;
|
||||||
public PRMgmtController(ErrorMessageService errorMessageService,
|
public PRMgmtController(ErrorMessageService errorMessageService,
|
||||||
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper,
|
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper,
|
||||||
IConfiguration configuration, IPRequest pRequest) :
|
IConfiguration configuration, IPRequest pRequest, IItem item) :
|
||||||
base(errorMessageService, webHostEnvironment, configuration)
|
base(errorMessageService, webHostEnvironment, configuration)
|
||||||
{
|
{
|
||||||
_config = configuration;
|
_config = configuration;
|
||||||
_smptHelper = sMTPHelper;
|
_smptHelper = sMTPHelper;
|
||||||
_pRequest = pRequest;
|
_pRequest = pRequest;
|
||||||
|
_item = item;
|
||||||
}
|
}
|
||||||
#region POST PUT
|
#region POST PUT
|
||||||
|
[HttpPost("PostPutAttachment")]
|
||||||
|
public async Task<IActionResult> PostPutAttachment([FromBody] PRVM PRDto)
|
||||||
|
{
|
||||||
|
var item = new AttachmentRequest()
|
||||||
|
{
|
||||||
|
PRId=PRDto.PRId,
|
||||||
|
FileName=PRDto.FileName,
|
||||||
|
OrigFileName=PRDto.OrigFileName,
|
||||||
|
};
|
||||||
|
await _item.PostPutAttachment(item);
|
||||||
|
return Ok(new { messCode = 1, message = "success"});
|
||||||
|
}
|
||||||
[HttpPost("ApprovedSelectedPRItem")]
|
[HttpPost("ApprovedSelectedPRItem")]
|
||||||
public async Task<IActionResult> ApprovedSelectedPRItem([FromBody] PRVM PRDto)
|
public async Task<IActionResult> ApprovedSelectedPRItem([FromBody] PRVM PRDto)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -255,6 +255,13 @@ namespace CPRNIMS.WebApps.Controllers.Items
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Get
|
#region Get
|
||||||
|
public async Task<IActionResult> GetProjectCode(string term)
|
||||||
|
{
|
||||||
|
var item = new ItemVM();
|
||||||
|
item.FileName = term;
|
||||||
|
response = await _item.GetProjectCode(GetUser(), item);
|
||||||
|
return GetResponse(response);
|
||||||
|
}
|
||||||
public async Task<IActionResult> GetImageFileIds()
|
public async Task<IActionResult> GetImageFileIds()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@ -21,24 +21,28 @@ namespace CPRNIMS.WebApps.Controllers.PR
|
|||||||
_pRequest = pRequest;
|
_pRequest = pRequest;
|
||||||
}
|
}
|
||||||
#region Get
|
#region Get
|
||||||
private async Task<IActionResult> GetProductFile(string fileName)
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetPRAttachment(string fileName)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Validate filename
|
|
||||||
if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
|
if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
|
||||||
{
|
{
|
||||||
return BadRequest("Invalid file name");
|
// Return a 400 Bad Request so the frontend 'catch' or '!response.ok' triggers
|
||||||
|
return BadRequest(new { success = false, message = "File does not exist!" });
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploadsPath = Path.Combine(_webHostEnvironment.WebRootPath, "Content/Uploads", "PRAttachment");
|
var uploadsPath = Path.Combine(_webHostEnvironment.WebRootPath, "Content/Uploads", "PRAttachment");
|
||||||
var filePath = Path.Combine(uploadsPath, fileName);
|
var filePath = Path.Combine(uploadsPath, fileName);
|
||||||
|
|
||||||
ContentTypeHelper.ValidateFile(filePath, uploadsPath);
|
if (!System.IO.File.Exists(filePath))
|
||||||
|
{
|
||||||
|
return NotFound(new { success = false, message = "File not found on server." });
|
||||||
|
}
|
||||||
|
|
||||||
// Stream the file instead of loading entirely into memory
|
// Stream the file for better performance
|
||||||
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
var contentType = ContentTypeHelper.GetContentType(fileName);
|
var contentType = "application/octet-stream"; // Or use a provider to get actual type
|
||||||
|
|
||||||
return File(fileStream, contentType, fileName, enableRangeProcessing: true);
|
return File(fileStream, contentType, fileName, enableRangeProcessing: true);
|
||||||
}
|
}
|
||||||
@ -47,6 +51,7 @@ namespace CPRNIMS.WebApps.Controllers.PR
|
|||||||
return StatusCode(500, "Error retrieving file");
|
return StatusCode(500, "Error retrieving file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IActionResult> GetProjectCodes(PRVM viewModels)
|
public async Task<IActionResult> GetProjectCodes(PRVM viewModels)
|
||||||
{
|
{
|
||||||
response = await _pRequest.GetProjectCodes(GetUser(), viewModels);
|
response = await _pRequest.GetProjectCodes(GetUser(), viewModels);
|
||||||
@ -150,6 +155,79 @@ namespace CPRNIMS.WebApps.Controllers.PR
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region POST PUT
|
#region POST PUT
|
||||||
|
public async Task<IActionResult?> UploadAttachment(IFormFile? file, [FromForm] string? oldFileName,
|
||||||
|
[FromForm] long prId)
|
||||||
|
{
|
||||||
|
var uploadsPath = Path.Combine(
|
||||||
|
_webHostEnvironment.WebRootPath,
|
||||||
|
"Content", "Uploads", "PRAttachment");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(uploadsPath);
|
||||||
|
|
||||||
|
// If no new file uploaded, return old filename
|
||||||
|
if (file == null)
|
||||||
|
return BadRequest(new { success = false, message = "File does not exist!" });
|
||||||
|
|
||||||
|
// Delete old file if exists
|
||||||
|
if (!string.IsNullOrWhiteSpace(oldFileName))
|
||||||
|
{
|
||||||
|
await DeleteAttachmentAsync(oldFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file extension
|
||||||
|
var allowedExtensions = new[] { ".csv", ".xlsx", ".xls", ".pdf" };
|
||||||
|
var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
|
||||||
|
|
||||||
|
if (!allowedExtensions.Contains(fileExtension))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Invalid file type. Only CSV, Excel, and PDF files are allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file size (5MB max)
|
||||||
|
if (file.Length > 5 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("File size exceeds 5MB limit.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate new unique filename with original extension
|
||||||
|
var newFileName = $"{Guid.NewGuid()}{fileExtension}";
|
||||||
|
var newFilePath = Path.Combine(uploadsPath, newFileName);
|
||||||
|
|
||||||
|
// Save new file
|
||||||
|
await using var stream = new FileStream(newFilePath, FileMode.Create);
|
||||||
|
await file.CopyToAsync(stream);
|
||||||
|
|
||||||
|
var prVM = new PRVM()
|
||||||
|
{
|
||||||
|
FileName = newFileName,
|
||||||
|
OrigFileName = file.FileName,
|
||||||
|
PRId = prId
|
||||||
|
};
|
||||||
|
var prResponse = await _pRequest.PostPutAttachment(GetUser(),prVM);
|
||||||
|
if (prResponse.messCode == 0) {
|
||||||
|
return BadRequest(new { success = false, message = "File does not exist!"});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return only filename (NOT full path)
|
||||||
|
return Json(new { success = true, message = "Attachment successfully uploaded!", newFileName = newFileName });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteAttachmentAsync(string fileName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(fileName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var uploadsPath = Path.Combine(
|
||||||
|
_webHostEnvironment.WebRootPath,
|
||||||
|
"Content", "Uploads", "PRAttachment");
|
||||||
|
|
||||||
|
var filePath = Path.Combine(uploadsPath, fileName);
|
||||||
|
|
||||||
|
if (System.IO.File.Exists(filePath))
|
||||||
|
{
|
||||||
|
await Task.Run(() => System.IO.File.Delete(filePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
public async Task<IActionResult> PostPutProjectCode([FromBody] PRVM viewModel)
|
public async Task<IActionResult> PostPutProjectCode([FromBody] PRVM viewModel)
|
||||||
{
|
{
|
||||||
var postPutItem = await _pRequest.PostPutProjectCode(GetUser(), viewModel);
|
var postPutItem = await _pRequest.PostPutProjectCode(GetUser(), viewModel);
|
||||||
|
|||||||
@ -113,7 +113,7 @@
|
|||||||
rows="4"
|
rows="4"
|
||||||
placeholder="Add any additional notes or comments here..."></textarea>
|
placeholder="Add any additional notes or comments here..."></textarea>
|
||||||
<div class="form-text">
|
<div class="form-text">
|
||||||
<span id="charCount">0</span>/500 characters
|
<span id="charCount">0</span>/100 characters
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -74,8 +74,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<link href="~/css/pr/TrackingV2.css" rel="stylesheet" />
|
<link href="~/css/pr/TrackingV3.css" rel="stylesheet" />
|
||||||
<link href="~/css/pr/buttonstyle.css" rel="stylesheet" />
|
<link href="~/css/pr/ButtonStyleV2.css" rel="stylesheet" />
|
||||||
@await Html.PartialAsync("PagesView/PR/_PRTracking")
|
@await Html.PartialAsync("PagesView/PR/_PRTracking")
|
||||||
<script src="~/JsFunctions/PR/PRV6.js"></script>
|
<script src="~/JsFunctions/PR/PRV6.js"></script>
|
||||||
@await Html.PartialAsync("PagesView/PR/_PRScripts")
|
@await Html.PartialAsync("PagesView/PR/_PRScripts")
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<input hidden id="roleRights" value="@ViewBag.UserRoles" />
|
<input hidden id="roleRights" value="@ViewBag.UserRoles" />
|
||||||
<link href="~/css/canvass/itemfortagging.css" rel="stylesheet" />
|
<link href="~/css/canvass/itemfortagging.css" rel="stylesheet" />
|
||||||
<link href="~/css/pr/buttonstyle.css" rel="stylesheet" />
|
<link href="~/css/pr/ButtonStyleV2.css" rel="stylesheet" />
|
||||||
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
|
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
|
||||||
<script src="~/JsFunctions/Canvass/canvassColumnV9.js"></script>
|
<script src="~/JsFunctions/Canvass/canvassColumnV9.js"></script>
|
||||||
<script src="~/JsFunctions/Canvass/canvassVarV3.js"></script>
|
<script src="~/JsFunctions/Canvass/canvassVarV3.js"></script>
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
<div id="loader" class="loader"></div>
|
<div id="loader" class="loader"></div>
|
||||||
</div>
|
</div>
|
||||||
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
|
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
|
||||||
|
|
||||||
<script src="~/jsfunctions/pr/PRColumnV7.js"></script>
|
<script src="~/jsfunctions/pr/PRColumnV7.js"></script>
|
||||||
<script src="~/jsfunctions/pr/PRViewV5.js"></script>
|
<script src="~/jsfunctions/pr/PRViewV5.js"></script>
|
||||||
<script src="~/jsfunctions/pr/PRPutPost.js"></script>
|
<script src="~/jsfunctions/pr/PRPutPost.js"></script>
|
||||||
|
|||||||
@ -337,60 +337,112 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="printableRelatedItem">
|
<div id="printableRelatedItem">
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<!-- PR Info Section -->
|
<!-- PR SUMMARY CARD -->
|
||||||
<div class="p-2 mb-3 rounded border shadow-sm bg-light pr-info-section">
|
<div class="card border-0 shadow-sm mb-4 pr-info-section">
|
||||||
<div class="row mb-2">
|
<div class="card-body">
|
||||||
<!-- PR No -->
|
|
||||||
<div class="col-md-5">
|
<div class="row g-3">
|
||||||
<small class="text-muted">P.R. No</small>
|
|
||||||
<div id="label-pr-prNo" class="fw-bold text-dark"></div>
|
<div class="col-md-3">
|
||||||
|
<div class="text-muted small">P.R. No</div>
|
||||||
|
<div id="label-pr-prNo" class="fw-bold fs-6"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- PR By -->
|
|
||||||
<div class="col-md-5">
|
<div class="col-md-3">
|
||||||
<small class="text-muted">P.R. By</small>
|
<div class="text-muted small">Date Needed</div>
|
||||||
<div id="label-prby" class="fw-bold text-dark"></div>
|
<div id="label-pr-dateNeeded" class="fw-semibold text-danger"></div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Department -->
|
|
||||||
<div class="col-md-5">
|
|
||||||
<small class="text-muted">Department</small>
|
<div class="col-md-3">
|
||||||
<div id="label-pr-Department" class="fw-bold text-dark"></div>
|
<div class="text-muted small">Department</div>
|
||||||
|
<div id="label-pr-Department" class="fw-semibold"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="text-muted small">Project Code</div>
|
||||||
|
<div id="label-pr-ProjectCode" class="fw-semibold"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="text-muted small">Requested By</div>
|
||||||
|
<div id="label-prby" class="fw-semibold"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="text-muted small">Attested By</div>
|
||||||
|
<div id="label-pr-attestedBy" class="fw-semibold"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="text-muted small">Approved By</div>
|
||||||
|
<div id="label-pr-approvedBy" class="fw-semibold"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="text-muted small">Remarks</div>
|
||||||
|
<div id="label-pr-remarks"
|
||||||
|
class="bg-light rounded p-2 small"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5">
|
|
||||||
<small class="text-muted">Project Code</small>
|
|
||||||
<div id="label-pr-ProjectCode" class="fw-bold text-dark"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-2">
|
<!-- SELECTION SUMMARY -->
|
||||||
<!-- Attested By -->
|
<div class="d-flex align-items-center mb-3 gap-2">
|
||||||
<div class="col-md-4">
|
<div>
|
||||||
<small class="text-muted">Attested By</small>
|
<span class="fw-semibold">Selected Items:</span>
|
||||||
<div id="label-pr-attestedBy" class="fw-bold text-dark"></div>
|
<span id="totalSelected" class="badge bg-danger ms-2">0</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- Approved By -->
|
<div>
|
||||||
<div class="col-md-4">
|
<button id="btnDownloadAttachment"
|
||||||
<small class="text-muted">Approved By</small>
|
class="btn btn-sm btn-outline-teal d-none"
|
||||||
<div id="label-pr-approvedBy" class="fw-bold text-dark"></div>
|
onclick="downloadPRAttachment()">
|
||||||
|
📎Export
|
||||||
|
</button>
|
||||||
|
<input hidden id="fileName" />
|
||||||
|
<input hidden id="origFileName" />
|
||||||
|
<input hidden id="prId" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- File Attachment Section -->
|
||||||
|
<div class="d-flex align-items-center gap-2 flex-grow-1">
|
||||||
|
<!-- File Input -->
|
||||||
|
<div class="file-upload-wrapper position-relative">
|
||||||
|
<input type="file"
|
||||||
|
class="form-control"
|
||||||
|
id="fileAttachment"
|
||||||
|
name="fileAttachment"
|
||||||
|
accept=".csv,.xlsx,.xls,.pdf"
|
||||||
|
style="max-width: 300px;" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- File Info Badge (shows when file selected) -->
|
||||||
|
<div id="fileInfoBadge" class="d-none">
|
||||||
|
<span class="badge bg-success-subtle text-success border border-success px-3 py-2">
|
||||||
|
<i class="bi bi-file-earmark-check me-1"></i>
|
||||||
|
<span id="fileNameDisplay" class="me-2"></span>
|
||||||
|
<small class="text-muted">(<span id="fileSizeDisplay"></span>)</small>
|
||||||
|
<button type="button"
|
||||||
|
class="btn-close btn-close-sm ms-2"
|
||||||
|
onclick="clearFileAttachment()"
|
||||||
|
style="font-size: 0.7rem; vertical-align: middle;"
|
||||||
|
title="Remove file"></button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Upload/Update Button (shows when file selected) -->
|
||||||
|
<div id="btnUploadContainer" class="d-none ms-auto">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-success btn-sm"
|
||||||
|
onclick="uploadAttachment()">
|
||||||
|
<i class="bi bi-cloud-upload me-1"></i>
|
||||||
|
<span id="btnUploadText">Upload Attachment</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- Date Needed -->
|
|
||||||
<div class="col-md-4">
|
|
||||||
<small class="text-muted">Date Needed</small>
|
|
||||||
<div id="label-pr-dateNeeded" class="fw-bold text-dark"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Requestor Remarks -->
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<small class="text-muted">Remarks</small>
|
|
||||||
<div id="label-pr-remarks" class="fw-bold text-dark"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<label for="totalSelected" style="font-size:medium;">Total Selected : </label>
|
|
||||||
<label id="totalSelected"
|
|
||||||
style="margin-bottom:20px; width:50px; font-weight:bold; color:red;"></label>
|
|
||||||
<br />
|
|
||||||
<table id="PRdataTable"
|
<table id="PRdataTable"
|
||||||
class="row-border" style="width: 100%;">
|
class="row-border" style="width: 100%;">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
@ -422,15 +474,31 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer pr-modal-footer">
|
||||||
<button type="button" class="btn btn-primary" onclick="resetIsApproval()" data-bs-dismiss="modal">Back</button>
|
<button type="button"
|
||||||
<button type="button" id="btnPrintPR" onclick="printPRItem();" class="btn btn-warning">Print</button>
|
class="btn btn-outline-secondary"
|
||||||
<button id="btnSubmitItem" type="button"
|
onclick="resetIsApproval()"
|
||||||
class="btn btn-success" onclick="approvedSelectedPRItem();">
|
data-bs-dismiss="modal">
|
||||||
Submit
|
Back
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
id="btnPrintPR"
|
||||||
|
onclick="printPRItem();"
|
||||||
|
class="btn btn-teal-warning">
|
||||||
|
🖨 Print
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button id="btnSubmitItem"
|
||||||
|
type="button"
|
||||||
|
class="btn btn-teal-primary"
|
||||||
|
onclick="approvedSelectedPRItem();">
|
||||||
|
✔ Approve Selected
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<input hidden id="roleRights" value="@ViewBag.UserRoles" />
|
<input hidden id="roleRights" value="@ViewBag.UserRoles" />
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -247,6 +247,17 @@ document.getElementById('fileAttachment').addEventListener('change', function (e
|
|||||||
filePreview.classList.remove('d-none');
|
filePreview.classList.remove('d-none');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
function formatFileSize(bytes) {
|
||||||
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
function clearFileAttachment() {
|
||||||
|
document.getElementById('fileAttachment').value = '';
|
||||||
|
document.getElementById('filePreview').classList.add('d-none');
|
||||||
|
}
|
||||||
function clearFormData() {
|
function clearFormData() {
|
||||||
document.getElementById('dateNeeded').value = '';
|
document.getElementById('dateNeeded').value = '';
|
||||||
document.getElementById('projectCode').value = '';
|
document.getElementById('projectCode').value = '';
|
||||||
@ -256,14 +267,10 @@ function clearFormData() {
|
|||||||
clearFileAttachment();
|
clearFileAttachment();
|
||||||
document.getElementById('charCount').textContent = '0';
|
document.getElementById('charCount').textContent = '0';
|
||||||
}
|
}
|
||||||
function clearFileAttachment() {
|
|
||||||
document.getElementById('fileAttachment').value = '';
|
|
||||||
document.getElementById('filePreview').classList.add('d-none');
|
|
||||||
}
|
|
||||||
document.getElementById('requestorRemarks').addEventListener('input', function (e) {
|
document.getElementById('requestorRemarks').addEventListener('input', function (e) {
|
||||||
const charCount = document.getElementById('charCount');
|
const charCount = document.getElementById('charCount');
|
||||||
const currentLength = e.target.value.length;
|
const currentLength = e.target.value.length;
|
||||||
const maxLength = 500;
|
const maxLength = 100;
|
||||||
|
|
||||||
charCount.textContent = currentLength;
|
charCount.textContent = currentLength;
|
||||||
|
|
||||||
@ -279,10 +286,4 @@ document.getElementById('requestorRemarks').addEventListener('input', function (
|
|||||||
charCount.classList.remove('text-danger');
|
charCount.classList.remove('text-danger');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
function formatFileSize(bytes) {
|
|
||||||
if (bytes === 0) return '0 Bytes';
|
|
||||||
const k = 1024;
|
|
||||||
const sizes = ['Bytes', 'KB', 'MB'];
|
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
||||||
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,32 +1,50 @@
|
|||||||
async function setupProjectCodeAutocomplete() {
|
function populateGetProjectCode() {
|
||||||
const input = document.getElementById('projectCode');
|
$("#projectCode").autocomplete({
|
||||||
let debounceTimer;
|
source: function (request, response) {
|
||||||
|
$.ajax({
|
||||||
|
url:'/ItemMgmt/GetProjectCode',
|
||||||
|
data: { query: request.term },
|
||||||
|
success: function (result) {
|
||||||
|
if (result && result.success && Array.isArray(result.data)) {
|
||||||
|
|
||||||
input.addEventListener('input', function (e) {
|
var formattedData = result.data.map(item => ({
|
||||||
clearTimeout(debounceTimer);
|
label: item.label || '',
|
||||||
const searchTerm = e.target.value;
|
value: item.value !== undefined && item.value !== null ? item.value.toString() : '',
|
||||||
|
value2: item.value2 !== undefined && item.value2 !== null ? item.value2.toString() : '',
|
||||||
if (searchTerm.length < 2) return;
|
value3: item.value3 !== undefined && item.value3 !== null ? item.value3.toString() : '',
|
||||||
|
value4: item.value4 !== undefined && item.value4 !== null ? item.value4.toString() : ''
|
||||||
debounceTimer = setTimeout(async () => {
|
}));
|
||||||
try {
|
response(formattedData);
|
||||||
// Replace with your actual API endpoint
|
} else {
|
||||||
const response = await fetch(`/api/projects/search?term=${encodeURIComponent(searchTerm)}`);
|
console.error('Invalid data format received:', result);
|
||||||
const projects = await response.json();
|
response([]);
|
||||||
|
}
|
||||||
const datalist = document.getElementById('projectCodeList');
|
}
|
||||||
datalist.innerHTML = '';
|
});
|
||||||
|
},
|
||||||
projects.forEach(project => {
|
minLength: 2,
|
||||||
const option = document.createElement('option');
|
select: function (event, ui) {
|
||||||
option.value = project.code;
|
$('#projectCodeList').val(ui.item.label);
|
||||||
option.textContent = `${project.code} - ${project.name}`;
|
$('#supplierId').val(ui.item.value);
|
||||||
datalist.appendChild(option);
|
|
||||||
});
|
return false;
|
||||||
} catch (error) {
|
},
|
||||||
console.error('Error fetching project codes:', error);
|
focus: function (event, ui) {
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
open: function () {
|
||||||
|
var dropdown = $(".ui-autocomplete");
|
||||||
|
dropdown.css({
|
||||||
|
"max-height": "200px",
|
||||||
|
"overflow-y": "auto"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
noResults: '',
|
||||||
|
results: function (count) {
|
||||||
|
return count + (count > 1 ? ' results' : ' result');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 300);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function populateItemCategSelect() {
|
function populateItemCategSelect() {
|
||||||
@ -420,6 +438,7 @@ function inputItemPopulation() {
|
|||||||
}
|
}
|
||||||
function showModal() {
|
function showModal() {
|
||||||
popltDeprtmntChargeTo();
|
popltDeprtmntChargeTo();
|
||||||
|
populateGetProjectCode();
|
||||||
$('#addDateNeeded').modal('show');
|
$('#addDateNeeded').modal('show');
|
||||||
$('#addDateNeeded').css('z-index', 1060);
|
$('#addDateNeeded').css('z-index', 1060);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,8 +19,6 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(requestData);
|
|
||||||
|
|
||||||
var DateNeeded = document.getElementById('dateNeeded').value;
|
var DateNeeded = document.getElementById('dateNeeded').value;
|
||||||
|
|
||||||
if (!DateNeeded) {
|
if (!DateNeeded) {
|
||||||
@ -234,91 +232,6 @@ function sendUpdateRequest(data, loader) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//function postPutPurchase() {
|
|
||||||
// loader = $('#overlay, #loader').css('z-index', 1060);
|
|
||||||
// isValid = true;
|
|
||||||
// var Remarks = document.getElementById('requestorRemarks').value;
|
|
||||||
// var selectedCheckboxes = $('.selectedItem-checkbox:checked');
|
|
||||||
// var requestData = [];
|
|
||||||
// selectedCheckboxes.each(function () {
|
|
||||||
// var $row = $(this).closest('tr');
|
|
||||||
// var rowIndex = itemTable.row($row).index();
|
|
||||||
// var rowData = itemTable.row(rowIndex).data();
|
|
||||||
|
|
||||||
// var itemCartId = rowData.itemCartId;
|
|
||||||
// var itemNo = rowData.itemNo;
|
|
||||||
// var qty = $row.find('.editable-qty').val() || rowData.qty;
|
|
||||||
|
|
||||||
// if (parseFloat(qty) === 0 || isNaN(parseFloat(qty))) {
|
|
||||||
// isValid = false;
|
|
||||||
// showToast('warning', "Please input a valid qty for ItemNo# " + itemNo + "!", ' warning', 4000);
|
|
||||||
// $(modalId).modal('hide');
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var itemData = {
|
|
||||||
// itemCartId: itemCartId,
|
|
||||||
// ItemNo: itemNo,
|
|
||||||
// qty: qty
|
|
||||||
// };
|
|
||||||
// requestData.push(itemData);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// if (selectedCheckboxes.length <= 0) {
|
|
||||||
// showToast('warning', 'No selected item!', 'Item cart failed', 4000);
|
|
||||||
// return;
|
|
||||||
// } else {
|
|
||||||
// var DateNeeded = document.getElementById('dateNeeded').value;
|
|
||||||
|
|
||||||
// if (!DateNeeded) {
|
|
||||||
// showToast('warning', 'Please choose date needed!', 'P.R. submission failed', 4000);
|
|
||||||
// confirmUpdateListener = false;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (RequestTypeId == 3) {
|
|
||||||
// updateDepartmentId();
|
|
||||||
// var ChargeTo = document.getElementById('departmentId').value;
|
|
||||||
// if (!ChargeTo) {
|
|
||||||
// showToast('warning', 'Please choose a department to be in charge of!', 'P.R. submission failed', 4000);
|
|
||||||
// confirmUpdateListener = false;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// showConfirmation({
|
|
||||||
// title: 'Purchasing Requisition',
|
|
||||||
// message: 'Are you sure you want to proceed? This action cannot be undone.',
|
|
||||||
// type: 'warning',
|
|
||||||
// confirmText: 'Yes',
|
|
||||||
// cancelText: 'No'
|
|
||||||
// }).then((confirmed) => {
|
|
||||||
// if (confirmed) {
|
|
||||||
// $.ajax({
|
|
||||||
// url: '/ItemMgmt/PostPurchRequest',
|
|
||||||
// type: 'POST',
|
|
||||||
// data: { ItemCartIds: requestData, DateNeeded: DateNeeded, RequestTypeId: RequestTypeId, ChargeTo: ChargeTo, Remarks: Remarks },
|
|
||||||
// success: function (response) {
|
|
||||||
// if (response.success) {
|
|
||||||
// itemTable.ajax.reload();
|
|
||||||
// $('#addDateNeeded').modal('hide');
|
|
||||||
// showToast('success', 'P.R. Successfully Created!', 'Success', 4000);
|
|
||||||
// var totalSelectedLabel = $('#totalSelected');
|
|
||||||
// totalSelectedLabel.text('');
|
|
||||||
// } else {
|
|
||||||
// itemTable.ajax.reload();
|
|
||||||
// showToast('error', response.response, title + ' failed', 4000);
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// beforeSend: function () {
|
|
||||||
// loader.show();
|
|
||||||
// },
|
|
||||||
// complete: function () {
|
|
||||||
// loader.hide();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//}
|
|
||||||
function AddToCart(isUpdated) {
|
function AddToCart(isUpdated) {
|
||||||
var loader = $('#overlay, #loader');
|
var loader = $('#overlay, #loader');
|
||||||
var ItemNo = $('#itemNo').val();
|
var ItemNo = $('#itemNo').val();
|
||||||
|
|||||||
@ -122,3 +122,151 @@ function submitItem() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const fileInput = document.getElementById('fileAttachment');
|
||||||
|
const fileInfoBadge = document.getElementById('fileInfoBadge');
|
||||||
|
const fileNameDisplay = document.getElementById('fileNameDisplay');
|
||||||
|
const fileSizeDisplay = document.getElementById('fileSizeDisplay');
|
||||||
|
const btnUploadContainer = document.getElementById('btnUploadContainer');
|
||||||
|
const btnUploadText = document.getElementById('btnUploadText');
|
||||||
|
|
||||||
|
let selectedFile = null;
|
||||||
|
let existingAttachment = false; // Set this to true if there's already an attachment
|
||||||
|
|
||||||
|
// File input change event
|
||||||
|
fileInput.addEventListener('change', function (e) {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
// Validate file size (5MB max)
|
||||||
|
const maxSize = 5 * 1024 * 1024; // 5MB in bytes
|
||||||
|
if (file.size > maxSize) {
|
||||||
|
showToast('warning', 'File size exceeds 5MB. Please choose a smaller file.', 'File Upload', 4000);
|
||||||
|
e.target.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate file type
|
||||||
|
const allowedExtensions = ['csv', 'xlsx', 'xls', 'pdf'];
|
||||||
|
const fileExtension = file.name.split('.').pop().toLowerCase();
|
||||||
|
|
||||||
|
if (!allowedExtensions.includes(fileExtension)) {
|
||||||
|
showToast('warning', 'Invalid file type. Please upload CSV, Excel, or PDF files only.', 'File Upload', 4000);
|
||||||
|
e.target.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the selected file
|
||||||
|
selectedFile = file;
|
||||||
|
|
||||||
|
// Show file info and upload button
|
||||||
|
showFileInfo(file);
|
||||||
|
showUploadButton();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show file information
|
||||||
|
function showFileInfo(file) {
|
||||||
|
fileNameDisplay.textContent = truncateFileName(file.name, 30);
|
||||||
|
fileSizeDisplay.textContent = formatFileSize(file.size);
|
||||||
|
fileInfoBadge.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show upload button
|
||||||
|
function showUploadButton() {
|
||||||
|
// Change button text based on whether there's an existing attachment
|
||||||
|
if (existingAttachment) {
|
||||||
|
btnUploadText.innerHTML = '<i class="bi bi-arrow-repeat me-1"></i>Update Attachment';
|
||||||
|
} else {
|
||||||
|
btnUploadText.innerHTML = '<i class="bi bi-cloud-upload me-1"></i>Upload Attachment';
|
||||||
|
}
|
||||||
|
|
||||||
|
btnUploadContainer.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear file attachment
|
||||||
|
function clearFileAttachment() {
|
||||||
|
fileInput.value = '';
|
||||||
|
selectedFile = null;
|
||||||
|
fileInfoBadge.classList.add('d-none');
|
||||||
|
btnUploadContainer.classList.add('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload attachment function
|
||||||
|
function uploadAttachment() {
|
||||||
|
if (!selectedFile) {
|
||||||
|
showToast('warning', 'Please select a file first.', 'File Upload', 3000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', selectedFile);
|
||||||
|
formData.append('prId', $('#prId').val());
|
||||||
|
|
||||||
|
formData.append('oldFileName', $('#fileName').val());
|
||||||
|
|
||||||
|
// Show loading state
|
||||||
|
btnUploadText.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Uploading...';
|
||||||
|
document.querySelector('#btnUploadContainer button').disabled = true;
|
||||||
|
|
||||||
|
fetch('/PRMgmt/UploadAttachment', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
showToast('success', 'Attachment uploaded successfully!', 'File Upload', 3000);
|
||||||
|
existingAttachment = true;
|
||||||
|
|
||||||
|
$('#fileName').val(data.newFileName)
|
||||||
|
// Update the download button if needed
|
||||||
|
document.getElementById('btnDownloadAttachment').classList.remove('d-none');
|
||||||
|
|
||||||
|
clearFileAttachment();
|
||||||
|
} else {
|
||||||
|
showToast('error', data.message || 'Upload failed. Please try again.', 'File Upload', 4000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Upload error:', error);
|
||||||
|
showToast('error', 'An error occurred during upload.', 'File Upload', 4000);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
// Reset button state
|
||||||
|
document.querySelector('#btnUploadContainer button').disabled = false;
|
||||||
|
showUploadButton(); // Restore button text
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate long file names
|
||||||
|
function truncateFileName(fileName, maxLength) {
|
||||||
|
if (fileName.length <= maxLength) return fileName;
|
||||||
|
|
||||||
|
const extension = fileName.split('.').pop();
|
||||||
|
const nameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.'));
|
||||||
|
const truncatedName = nameWithoutExt.substring(0, maxLength - extension.length - 4) + '...';
|
||||||
|
|
||||||
|
return truncatedName + '.' + extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format file size
|
||||||
|
function formatFileSize(bytes) {
|
||||||
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize: Check if there's an existing attachment on page load
|
||||||
|
function checkExistingAttachment() {
|
||||||
|
// Replace with your logic to check if attachment exists
|
||||||
|
// For example, check if there's a filename in your hidden input
|
||||||
|
const existingFileName = document.getElementById('fileName').value;
|
||||||
|
|
||||||
|
if (existingFileName) {
|
||||||
|
existingAttachment = true;
|
||||||
|
document.getElementById('btnDownloadAttachment').classList.remove('d-none');
|
||||||
|
} else {
|
||||||
|
existingAttachment = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -55,7 +55,6 @@
|
|||||||
|
|
||||||
modal.modal('show');
|
modal.modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getApproverName(prDetailsId) {
|
function getApproverName(prDetailsId) {
|
||||||
PRDetailsId = prDetailsId;
|
PRDetailsId = prDetailsId;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -90,106 +89,111 @@ function printPRItem() {
|
|||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
|
|
||||||
const doc = iframe.contentWindow.document;
|
const doc = iframe.contentWindow.document;
|
||||||
|
|
||||||
doc.open();
|
doc.open();
|
||||||
doc.write('<html><head><title>Print</title>');
|
doc.write('<!DOCTYPE html><html><head>');
|
||||||
|
doc.write('<meta charset="UTF-8">');
|
||||||
|
|
||||||
|
// Copy all stylesheets INCLUDING Bootstrap
|
||||||
const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
|
const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
|
||||||
stylesheets.forEach(sheet => {
|
stylesheets.forEach(sheet => {
|
||||||
doc.write(sheet.outerHTML);
|
doc.write(sheet.outerHTML);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Copy all inline styles
|
||||||
|
const styles = document.querySelectorAll('style');
|
||||||
|
styles.forEach(style => {
|
||||||
|
doc.write(style.outerHTML);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add additional print styles
|
||||||
doc.write(`
|
doc.write(`
|
||||||
<style>
|
<style>
|
||||||
@media print {
|
@media print {
|
||||||
.pr-info-section .row {
|
/* Reduce overall print font */
|
||||||
display: flex !important;
|
|
||||||
flex-wrap: nowrap !important;
|
|
||||||
}
|
|
||||||
.pr-info-section .col-md-4 {
|
|
||||||
flex: 0 0 33.33% !important;
|
|
||||||
max-width: 33.33% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
table-layout: fixed !important;
|
|
||||||
width: 125% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide the 5th and 6th columns */
|
|
||||||
/* Hide the 5th and 6th columns */
|
|
||||||
table th:nth-child(5),
|
|
||||||
table th:nth-child(6),
|
|
||||||
table td:nth-child(5),
|
|
||||||
table td:nth-child(6) {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
table th:not(:nth-child(5)):not(:nth-child(6)),
|
|
||||||
table td:not(:nth-child(5)):not(:nth-child(6)) {
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-break {
|
|
||||||
page-break-before: always;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: Roman, sans-serif;
|
font-size: 10px !important;
|
||||||
font-size: 12px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
font-family: Roman, sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
padding: 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reduce vertical padding inside table rows */
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: Roman, sans-serif;
|
|
||||||
}
|
|
||||||
table th,
|
|
||||||
table td {
|
|
||||||
padding: 2px 2px;
|
|
||||||
line-height: 1.2;
|
|
||||||
vertical-align: top;
|
|
||||||
border: .5px solid #808080 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reduce PR Info Section font */
|
||||||
.pr-info-section {
|
.pr-info-section {
|
||||||
font-size: 10px !important;
|
font-size: 10px !important;
|
||||||
background: #f8f9fa !important;
|
margin-bottom: 5px !important;
|
||||||
border: 1px solid #dee2e6 !important;
|
page-break-inside: avoid !important;
|
||||||
padding: 8px !important;
|
|
||||||
margin-bottom: 10px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pr-info-section label,
|
|
||||||
.pr-info-section strong,
|
|
||||||
.pr-info-section .fw-bold {
|
|
||||||
font-size: 10px !important;
|
|
||||||
font-weight: bold !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make PR info labels slightly smaller */
|
||||||
|
.pr-info-section small,
|
||||||
.pr-info-section .text-muted {
|
.pr-info-section .text-muted {
|
||||||
font-size: 9px !important;
|
font-size: 9px !important;
|
||||||
color: #666 !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide DataTables controls */
|
/* Reduce table body font */
|
||||||
.dataTables_length,
|
table {
|
||||||
.dataTables_filter,
|
font-size: 9px !important;
|
||||||
.dataTables_info,
|
border-collapse: collapse;
|
||||||
.dataTables_paginate {
|
}
|
||||||
display: none !important;
|
|
||||||
|
/* Keep header slightly larger for readability */
|
||||||
|
th {
|
||||||
|
font-size: 11px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce table padding */
|
||||||
|
th, td {
|
||||||
|
padding: 3px 4px !important;
|
||||||
|
border: 1px #ddd;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Ensure Bootstrap grid works in print */
|
||||||
|
.row {
|
||||||
|
display: flex !important;
|
||||||
|
flex-wrap: wrap !important;
|
||||||
|
margin-right: -10px !important;
|
||||||
|
margin-left: -10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-md-3 {
|
||||||
|
flex: 0 0 25% !important;
|
||||||
|
max-width: 25% !important;
|
||||||
|
padding-right: 10px !important;
|
||||||
|
padding-left: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: 1px #ddd !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #444 !important;
|
||||||
|
color: white !important;
|
||||||
|
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(even) {
|
||||||
|
background-color: #666 !important;
|
||||||
|
color: white !important;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(odd) {
|
||||||
|
background-color: #f9f9f9 !important;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
@page {
|
||||||
|
margin: 0.5in;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
`);
|
`);
|
||||||
@ -197,13 +201,14 @@ function printPRItem() {
|
|||||||
doc.write('</head><body>');
|
doc.write('</head><body>');
|
||||||
|
|
||||||
// Add the main header
|
// Add the main header
|
||||||
doc.write('<div class="header">Purchase Requisition Details</div>');
|
doc.write('<div style="text-align: center; margin-bottom: 20px;"><h5>Purchase Requisition Details</h5></div>');
|
||||||
|
|
||||||
// Get the PR info section HTML
|
// Get the PR info section HTML and preserve its exact structure
|
||||||
const prInfoSection = document.querySelector('.pr-info-section');
|
const prInfoSection = document.querySelector('.pr-info-section');
|
||||||
let prInfoHTML = '';
|
let prInfoHTML = '';
|
||||||
if (prInfoSection) {
|
if (prInfoSection) {
|
||||||
prInfoHTML = prInfoSection.outerHTML;
|
const clonedPrInfo = prInfoSection.cloneNode(true);
|
||||||
|
prInfoHTML = clonedPrInfo.outerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone the printable content
|
// Clone the printable content
|
||||||
@ -220,19 +225,48 @@ function printPRItem() {
|
|||||||
// Get the table
|
// Get the table
|
||||||
const table = printContent.querySelector('table');
|
const table = printContent.querySelector('table');
|
||||||
if (table) {
|
if (table) {
|
||||||
const tbody = table.querySelector('tbody');
|
|
||||||
const rows = Array.from(tbody.querySelectorAll('tr'));
|
|
||||||
const rowsPerPage = 50; // Reduced to accommodate PR info section
|
|
||||||
|
|
||||||
// Create table header HTML
|
|
||||||
const thead = table.querySelector('thead');
|
const thead = table.querySelector('thead');
|
||||||
|
const tbody = table.querySelector('tbody');
|
||||||
|
|
||||||
|
// Remove unwanted columns from header
|
||||||
|
if (thead) {
|
||||||
|
const headerRows = thead.querySelectorAll('tr');
|
||||||
|
headerRows.forEach(row => {
|
||||||
|
const cells = Array.from(row.querySelectorAll('th'));
|
||||||
|
// Count total cells
|
||||||
|
const totalCells = cells.length;
|
||||||
|
|
||||||
|
// Remove Action column (last)
|
||||||
|
if (cells[totalCells - 1]) cells[totalCells - 1].remove();
|
||||||
|
// Remove Status column (second to last)
|
||||||
|
if (cells[totalCells - 2]) cells[totalCells - 2].remove();
|
||||||
|
// Remove checkbox column (first)
|
||||||
|
if (cells[0]) cells[0].remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove unwanted columns from body rows
|
||||||
|
const rows = Array.from(tbody.querySelectorAll('tr'));
|
||||||
|
rows.forEach(row => {
|
||||||
|
const cells = Array.from(row.querySelectorAll('td'));
|
||||||
|
const totalCells = cells.length;
|
||||||
|
|
||||||
|
// Remove Action column (last)
|
||||||
|
if (cells[totalCells - 1]) cells[totalCells - 1].remove();
|
||||||
|
// Remove Status column (second to last)
|
||||||
|
if (cells[totalCells - 2]) cells[totalCells - 2].remove();
|
||||||
|
// Remove checkbox column (first)
|
||||||
|
if (cells[0]) cells[0].remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
const rowsPerPage = 50;
|
||||||
const tableHeaderHTML = thead ? thead.outerHTML : '';
|
const tableHeaderHTML = thead ? thead.outerHTML : '';
|
||||||
|
|
||||||
// Split into pages
|
// Split into pages
|
||||||
for (let i = 0; i < rows.length; i += rowsPerPage) {
|
for (let i = 0; i < rows.length; i += rowsPerPage) {
|
||||||
// Add page break for pages after the first
|
// Add page break for pages after the first
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
doc.write('<div class="page-break"></div>');
|
doc.write('<div style="page-break-before: always;"></div>');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add PR info section to every page
|
// Add PR info section to every page
|
||||||
@ -242,20 +276,8 @@ function printPRItem() {
|
|||||||
const currentPageRows = rows.slice(i, i + rowsPerPage);
|
const currentPageRows = rows.slice(i, i + rowsPerPage);
|
||||||
|
|
||||||
// Create table for current page
|
// Create table for current page
|
||||||
doc.write('<table class="row-border" style="width: 100%;">');
|
doc.write('<table>');
|
||||||
doc.write('<colgroup>');
|
|
||||||
doc.write('<col style="width:8%" />');
|
|
||||||
doc.write('<col style="width:30%" />');
|
|
||||||
doc.write('<col style="width:34%" />');
|
|
||||||
doc.write('<col style="width:8%" />');
|
|
||||||
doc.write('<col style="width:8%" />');
|
|
||||||
doc.write('<col style="width:12%" />');
|
|
||||||
doc.write('</colgroup>');
|
|
||||||
|
|
||||||
// Add table header
|
|
||||||
doc.write(tableHeaderHTML);
|
doc.write(tableHeaderHTML);
|
||||||
|
|
||||||
// Add table body with current page rows
|
|
||||||
doc.write('<tbody>');
|
doc.write('<tbody>');
|
||||||
currentPageRows.forEach(row => {
|
currentPageRows.forEach(row => {
|
||||||
doc.write(row.outerHTML);
|
doc.write(row.outerHTML);
|
||||||
@ -264,7 +286,7 @@ function printPRItem() {
|
|||||||
doc.write('</table>');
|
doc.write('</table>');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback: just add PR info and content
|
// Fallback
|
||||||
doc.write(prInfoHTML);
|
doc.write(prInfoHTML);
|
||||||
doc.write(printContent.innerHTML);
|
doc.write(printContent.innerHTML);
|
||||||
}
|
}
|
||||||
@ -275,16 +297,17 @@ function printPRItem() {
|
|||||||
|
|
||||||
// Wait for the iframe to load before printing
|
// Wait for the iframe to load before printing
|
||||||
iframe.onload = function () {
|
iframe.onload = function () {
|
||||||
// Print the iframe content
|
// Small delay to ensure styles are loaded
|
||||||
|
setTimeout(function () {
|
||||||
iframe.contentWindow.print();
|
iframe.contentWindow.print();
|
||||||
|
|
||||||
// Remove the iframe after printing
|
// Remove the iframe after printing
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
document.body.removeChild(iframe);
|
document.body.removeChild(iframe);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
}, 500);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function viewItemRemovalRemarks(data) {
|
function viewItemRemovalRemarks(data) {
|
||||||
PRDetailsId = data.prDetailsId;
|
PRDetailsId = data.prDetailsId;
|
||||||
ItemName = data.itemName;
|
ItemName = data.itemName;
|
||||||
@ -696,7 +719,8 @@ function viewPRDetails(data) {
|
|||||||
document.getElementById('label-pr-approvedBy').innerHTML = data.approvedBy;
|
document.getElementById('label-pr-approvedBy').innerHTML = data.approvedBy;
|
||||||
document.getElementById('label-pr-ProjectCode').innerHTML = data.projectCode;
|
document.getElementById('label-pr-ProjectCode').innerHTML = data.projectCode;
|
||||||
|
|
||||||
console.log('data.projectCode', data.projectCode);
|
$('#prId').val(data.prId);
|
||||||
|
console.log('data.prId', data.prId);
|
||||||
|
|
||||||
document.getElementById('label-pr-dateNeeded').innerHTML = formatDate(data.dateNeeded);
|
document.getElementById('label-pr-dateNeeded').innerHTML = formatDate(data.dateNeeded);
|
||||||
|
|
||||||
@ -712,6 +736,27 @@ function viewPRDetails(data) {
|
|||||||
emptyTable: "No record available"
|
emptyTable: "No record available"
|
||||||
},
|
},
|
||||||
initComplete: function () {
|
initComplete: function () {
|
||||||
|
var api = this.api();
|
||||||
|
var response = api.ajax.json();
|
||||||
|
|
||||||
|
// 1. Find the first row that actually has a fileName
|
||||||
|
const rowWithFile = response?.data?.find(
|
||||||
|
row => row.fileName && row.fileName.trim() !== ''
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. If a file exists, update the hidden inputs and show the button
|
||||||
|
if (rowWithFile) {
|
||||||
|
$('#fileName').val(rowWithFile.fileName);
|
||||||
|
$('#origFileName').val(rowWithFile.origFileName || ''); // Use empty string if null
|
||||||
|
$('#btnDownloadAttachment').removeClass('d-none');
|
||||||
|
} else {
|
||||||
|
// Clear values and hide button if no attachment is found
|
||||||
|
$('#fileName').val('');
|
||||||
|
$('#origFileName').val('');
|
||||||
|
$('#btnDownloadAttachment').addClass('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep your selection initialization
|
||||||
initializeTableSelection({
|
initializeTableSelection({
|
||||||
tableName: tableName,
|
tableName: tableName,
|
||||||
dataTable: prDataTable,
|
dataTable: prDataTable,
|
||||||
@ -727,11 +772,43 @@ function viewPRDetails(data) {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
columns: colItemList,
|
columns: colItemList,
|
||||||
// responsive: true,
|
pageLength: 5,
|
||||||
|
lengthMenu: [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, "All"]],
|
||||||
rowCallback: rowStatusColorCallback,
|
rowCallback: rowStatusColorCallback,
|
||||||
error: errorHandler
|
error: errorHandler
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function downloadPRAttachment() {
|
||||||
|
let fileName = $('#fileName').val();
|
||||||
|
|
||||||
|
// Append parameters to URL for GET requests
|
||||||
|
const params = new URLSearchParams({ fileName: fileName });
|
||||||
|
const url = `/PRMgmt/GetPRAttachment?${params.toString()}`;
|
||||||
|
|
||||||
|
fetch(url, { method: 'GET' })
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
// If backend returns 500 or 400, it won't be a blob
|
||||||
|
throw new Error("Failed to download file");
|
||||||
|
}
|
||||||
|
return response.blob();
|
||||||
|
})
|
||||||
|
.then(blob => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = fileName;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Error downloading attachment:", error);
|
||||||
|
alert("Error downloading attachment. Please check if the file exists.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function clearTextModal() {
|
function clearTextModal() {
|
||||||
if (UserRights == 'LLISCMAdmin' || UserRights == 'LTReceiver') {
|
if (UserRights == 'LLISCMAdmin' || UserRights == 'LTReceiver') {
|
||||||
document.getElementById('docTypeId').value = "";
|
document.getElementById('docTypeId').value = "";
|
||||||
|
|||||||
@ -18,3 +18,26 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
.pr-modal-footer {
|
||||||
|
background: #f1f5f9;
|
||||||
|
border-top: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Teal primary button */
|
||||||
|
.btn-teal-primary {
|
||||||
|
background-color: #0f766e;
|
||||||
|
border-color: #0f766e;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-teal-primary:hover {
|
||||||
|
background-color: #115e59;
|
||||||
|
border-color: #115e59;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Soft warning */
|
||||||
|
.btn-teal-warning {
|
||||||
|
background-color: #f59e0b;
|
||||||
|
border-color: #f59e0b;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
@ -133,6 +133,14 @@ textarea {
|
|||||||
.modal-footer .btn {
|
.modal-footer .btn {
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
}
|
}
|
||||||
|
.pr-table-header {
|
||||||
|
background-color: #0f766e;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-table-header th {
|
||||||
|
border-color: #0f766e;
|
||||||
|
}
|
||||||
|
|
||||||
.form-row .col {
|
.form-row .col {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
@ -170,3 +178,53 @@ textarea {
|
|||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
box-shadow: 0 4px 10px rgba(0,0,0,0.2)
|
box-shadow: 0 4px 10px rgba(0,0,0,0.2)
|
||||||
}
|
}
|
||||||
|
.btn-outline-teal {
|
||||||
|
color: #0f766e;
|
||||||
|
border: 1px solid #0f766e;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline-teal:hover {
|
||||||
|
background-color: #0f766e;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* File upload styling */
|
||||||
|
.file-upload-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fileAttachment {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fileInfoBadge .badge {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fileInfoBadge .btn-close {
|
||||||
|
padding: 0;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fileInfoBadge .btn-close:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smooth transitions */
|
||||||
|
#fileInfoBadge, #btnUploadContainer {
|
||||||
|
animation: fadeInRight 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeInRight {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user