From 7cf4852256d61b8043b616b712c7cd04d2b42bf8 Mon Sep 17 00:00:00 2001 From: rowell_m_soriano Date: Wed, 1 Jul 2026 07:07:26 +0800 Subject: [PATCH] UploadPath change to new path C:\\inetpub\\cprnims-web\\wwwroot\\Content\\Images --- .gitea/workflows/deploy.yml | 43 +- CPRNIMS.Domain/Services/Account/Account.cs | 26 +- .../ViewModel/Account/RegisterVM.cs | 4 +- .../Controllers/Account/AnonController.cs | 2 +- .../Controllers/Account/AccountController.cs | 23 +- CPRNIMS.WebApps/Program.cs | 1 - CPRNIMS.WebApps/Views/Account/Index.cshtml | 961 ++---------------- CPRNIMS.WebApps/appsettings.json | 2 +- .../JsFunctions/Account/AccountPostPut.js | 5 +- .../wwwroot/JsFunctions/Account/index.js | 324 ++---- .../JsFunctions/Account/sessionTimeoutV5.js | 12 +- .../wwwroot/css/Account/UserAccount.css | 817 +++++++++++++++ 12 files changed, 1044 insertions(+), 1176 deletions(-) create mode 100644 CPRNIMS.WebApps/wwwroot/css/Account/UserAccount.css diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index daf413f..ec321a0 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -63,7 +63,7 @@ jobs: $json = $config | ConvertTo-Json -Depth 5 $json | Out-File -FilePath "C:\ci-output\webapi\appsettings.Production.json" -Encoding utf8 - Write-Host "Wrote appsettings.Production.json to webapi output (values masked in this log automatically)" + Write-Host "Wrote appsettings.Production.json to webapi output (secret values not echoed)" exit 0 # ---- Generate production config for WebApps (uses Variables, not Secrets, since BaseUrl is not sensitive) ---- @@ -100,10 +100,10 @@ jobs: if (Test-Path "C:\inetpub\cprnims-api") { robocopy "C:\inetpub\cprnims-api" "C:\backups\$stamp\webapi" /MIR /R:2 /W:3 | Out-Null } - # Exclude dynamic user images from backup - not part of deployable artifact + # Exclude dynamic user images by folder NAME so the exclusion always matches + # regardless of source/destination path direction. if (Test-Path "C:\inetpub\cprnims-web") { - robocopy "C:\inetpub\cprnims-web" "C:\backups\$stamp\webapps" /MIR /R:2 /W:3 ` - /XD "C:\inetpub\cprnims-web\wwwroot\Content\Images" | Out-Null + robocopy "C:\inetpub\cprnims-web" "C:\backups\$stamp\webapps" /MIR /R:2 /W:3 /XD Images | Out-Null } $stamp | Out-File -FilePath "C:\backups\latest.txt" -Encoding ascii -NoNewline @@ -142,33 +142,18 @@ jobs: shell: pwsh run: | # Deploy everything EXCEPT the dynamic images folder. - # /XD excludes the Images directory itself from mirroring (prevents deletion of subfolders). - # We use the destination full path for /XD so only this specific Images folder is protected, - # not any other folder named Images elsewhere in the tree. - # Note: files sitting directly inside Images\ are protected because /XD stops robocopy - # from treating that directory as part of the mirror scope entirely. - robocopy "C:\ci-output\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 ` - /XD "C:\inetpub\cprnims-web\wwwroot\Content\Images" + # /XD Images excludes the directory by NAME, which robocopy matches reliably + # against the source tree it walks. This prevents /MIR from purging the live + # C:\inetpub\cprnims-web\wwwroot\Content\Images folder where end users upload images. + # NOTE: the build output contains no images, so there is nothing to re-seed - + # the live Images folder must simply be left untouched. + robocopy "C:\ci-output\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 /XD Images $rc = $LASTEXITCODE Write-Host "ROBOCOPY EXIT CODE: $rc" if ($rc -ge 8) { throw "robocopy failed for WebApps with exit code $rc" } - - # Separately sync only the static seed images that ARE part of the repo - # (1.jpg, 2.jpg, 3.jpg, 404userImage.jpg) without /PURGE or /MIR, - # so new files from the build are added but existing dynamic uploads are never deleted. - if (Test-Path "C:\ci-output\webapps\wwwroot\Content\Images") { - robocopy "C:\ci-output\webapps\wwwroot\Content\Images" ` - "C:\inetpub\cprnims-web\wwwroot\Content\Images" ` - /E /R:3 /W:5 - $rc2 = $LASTEXITCODE - Write-Host "ROBOCOPY IMAGES EXIT CODE: $rc2" - if ($rc2 -ge 8) { - throw "robocopy failed for Images folder with exit code $rc2" - } - } exit 0 - name: Start app pools @@ -196,7 +181,7 @@ jobs: if: failure() shell: pwsh run: | - $stamp = Get-Content "C:\backups\latest.txt" -Raw + $stamp = (Get-Content "C:\backups\latest.txt" -Raw).Trim() $backupPath = "C:\backups\$stamp" Write-Host "Deployment failed - rolling back to backup: $backupPath" @@ -208,10 +193,10 @@ jobs: if (Test-Path "$backupPath\webapi") { robocopy "$backupPath\webapi" "C:\inetpub\cprnims-api" /MIR /R:3 /W:5 | Out-Null } - # Exclude dynamic images from rollback restore - preserve images uploaded after the backup was taken + # Exclude Images by name on rollback too - the backup never contains Images, + # so without this /MIR would DELETE the live user-uploaded images. if (Test-Path "$backupPath\webapps") { - robocopy "$backupPath\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 ` - /XD "C:\inetpub\cprnims-web\wwwroot\Content\Images" | Out-Null + robocopy "$backupPath\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 /XD Images | Out-Null } Start-WebAppPool -Name "CPRNIMS-Api" diff --git a/CPRNIMS.Domain/Services/Account/Account.cs b/CPRNIMS.Domain/Services/Account/Account.cs index f6844f3..c786c8a 100644 --- a/CPRNIMS.Domain/Services/Account/Account.cs +++ b/CPRNIMS.Domain/Services/Account/Account.cs @@ -119,24 +119,16 @@ namespace CPRNIMS.Domain.Services.Account public async Task PutPostUserAccess(AccountDto itemDto) { - try - { - await _accountDbContext.Database - .ExecuteSqlRawAsync("EXEC PutPostUserAccess @ContAccId,@AdminUserId,@UserId,@AccessTypeId,@UserAccessId,@IsActive", - new SqlParameter("@ContAccId", itemDto.ContAccId), - new SqlParameter("@AdminUserId", itemDto.AdminUserId), - new SqlParameter("@UserId", itemDto.UserId), - new SqlParameter("@AccessTypeId", itemDto.AccessTypeId), - new SqlParameter("@UserAccessId", itemDto.UserAccessId), - new SqlParameter("@IsActive", itemDto.IsActive)); + await _accountDbContext.Database + .ExecuteSqlRawAsync("EXEC PutPostUserAccess @ContAccId,@AdminUserId,@UserId,@AccessTypeId,@UserAccessId,@IsActive", + new SqlParameter("@ContAccId", itemDto.ContAccId), + new SqlParameter("@AdminUserId", itemDto.AdminUserId), + new SqlParameter("@UserId", itemDto.UserId), + new SqlParameter("@AccessTypeId", itemDto.AccessTypeId), + new SqlParameter("@UserAccessId", itemDto.UserAccessId), + new SqlParameter("@IsActive", itemDto.IsActive)); - return new UserRights(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return new UserRights(); } } } diff --git a/CPRNIMS.Infrastructure/ViewModel/Account/RegisterVM.cs b/CPRNIMS.Infrastructure/ViewModel/Account/RegisterVM.cs index 8c913ca..6aa2d66 100644 --- a/CPRNIMS.Infrastructure/ViewModel/Account/RegisterVM.cs +++ b/CPRNIMS.Infrastructure/ViewModel/Account/RegisterVM.cs @@ -28,7 +28,7 @@ namespace CPRNIMS.Infrastructure.ViewModel.Account public AttachmentVM? Attachment { get; set; } public string? ProfilePictureStr { get; set; } public string? NewPassword { get; set; } - public string UserId { get; set; } - public string PasswordHash { get; set; } + public string UserId { get; set; }= string.Empty; + public string? PasswordHash { get; set; } } } diff --git a/CPRNIMS.WebApi/Controllers/Account/AnonController.cs b/CPRNIMS.WebApi/Controllers/Account/AnonController.cs index 14770f0..ed1f0de 100644 --- a/CPRNIMS.WebApi/Controllers/Account/AnonController.cs +++ b/CPRNIMS.WebApi/Controllers/Account/AnonController.cs @@ -112,7 +112,7 @@ namespace CPRNIMS.WebApi.Controllers.Account if (user.AccessFailedCount > 3 || signInResult.IsLockedOut) { await _userManager.SetLockoutEnabledAsync(user, true); - await _userManager.SetLockoutEndDateAsync(user, DateTime.Now.AddMinutes(30)); + await _userManager.SetLockoutEndDateAsync(user, DateTime.Now.AddHours(2)); return BadRequest(new ResponseObject { diff --git a/CPRNIMS.WebApps/Controllers/Account/AccountController.cs b/CPRNIMS.WebApps/Controllers/Account/AccountController.cs index 1cb5d2e..cc52f5c 100644 --- a/CPRNIMS.WebApps/Controllers/Account/AccountController.cs +++ b/CPRNIMS.WebApps/Controllers/Account/AccountController.cs @@ -215,27 +215,10 @@ namespace CPRNIMS.WebApps.Controllers.Account } public async Task GetRoles() { - try - { - var response = await _account.GetRoles(GetUser()); + var viewModels = new UserRightsVM(); + var response = await _account.GetRoles(GetUser()); - if (response != null) - { - // return Json(new { data = response }); - return new JsonResult(new { data = response }); - - } - else - { - return RedirectToAction("Logout", "Home"); - } - } - catch (Exception ex) - { - var message = ex.InnerException?.ToString() ?? ex.Message.ToString(); - - return Json(new { data = "No Data" }); - } + return GetResponse(response); } [HttpGet] public async Task GetUserRights(UserRightsVM viewModel) diff --git a/CPRNIMS.WebApps/Program.cs b/CPRNIMS.WebApps/Program.cs index a394bfa..42e416d 100644 --- a/CPRNIMS.WebApps/Program.cs +++ b/CPRNIMS.WebApps/Program.cs @@ -1,6 +1,5 @@ using CPRNIMS.Domain.UIServices.Updater; using CPRNIMS.WebApps.Common; -using Microsoft.AspNetCore.StaticFiles; var builder = WebApplication.CreateBuilder(args); diff --git a/CPRNIMS.WebApps/Views/Account/Index.cshtml b/CPRNIMS.WebApps/Views/Account/Index.cshtml index 9297fa1..5189a27 100644 --- a/CPRNIMS.WebApps/Views/Account/Index.cshtml +++ b/CPRNIMS.WebApps/Views/Account/Index.cshtml @@ -1,824 +1,6 @@ User Management - - + @@ -861,8 +43,14 @@

List of Users

@@ -881,9 +69,6 @@ Created Date Updated By Updated Date - - - @@ -913,40 +98,46 @@ @@ -1168,19 +359,7 @@ { data: 'updatedBy' }, // [10] Updated Date { data: 'updatedDate', render: d => formatDate(d) }, - // [11] ID — hidden - { data: 'id', visible: false }, - // [12] Address — hidden - { data: 'address', visible: false }, - // [13] Profile picture — hidden - { - data: null, - visible: false, - render: (d, t, row) => `profilePicture` - } ], - - columnDefs: colOnColDef, language: { emptyTable: "No record available" }, rowCallback: rowAccountCallback, responsive: true, @@ -1196,7 +375,7 @@ }); }); - function filterTable(value) { + function filterTable(value) { if (userListTable) { userListTable.search(value).draw(); } @@ -1246,7 +425,6 @@ return html; } - // ═══════════════════════════════════════════════════════ // Existing Access Rights functions // Bootstrap modals — kept exactly as your original logic @@ -1254,7 +432,7 @@ function viewUserAccess(data) { loader = $('#overlay, #loader'); - + isNotExist=1; UserId = data.id; document.getElementById('btnAddAccess').style.display='block'; @@ -1331,6 +509,7 @@ var submitButton = $('#btnNotAccess'); var totalSelectedLabel = $('#totalSelNotAccess'); var IsNotExist = true; + isNotExist=13; openModal('modalAccess'); @@ -1449,10 +628,25 @@ // ═══════════════════════════════════════════════════════ // Custom modal helpers (new UI overlay modals) // ═══════════════════════════════════════════════════════ + let departmentLoaded = false; + let roleLoaded = false; function openModal(id) { const el = document.getElementById(id); - if (el) el.classList.add('show'); + if (!el) return; + + el.classList.add('show'); + + if (id === 'modalCreate') { + if (!departmentLoaded) { + populateDepartment(); + departmentLoaded = true; + } + if (!roleLoaded) { + populateRoles(); + roleLoaded = true; + } + } } function closeModal(id) { @@ -1460,6 +654,68 @@ if (el) el.classList.remove('show'); } + function shakeModal(overlayEl) { + const box = overlayEl.querySelector('.modal-box'); + if (!box) return; + box.classList.remove('shake'); + void box.offsetWidth; // force reflow to replay animation + box.classList.add('shake'); + } + + document.addEventListener('DOMContentLoaded', () => { + document.querySelectorAll('.modal-overlay').forEach(overlay => { + let pressStartedOnOverlay = false; + + // Track where the press STARTED + overlay.addEventListener('mousedown', (e) => { + pressStartedOnOverlay = (e.target === overlay); + }); + + // Only shake if BOTH press and release happened on the overlay + overlay.addEventListener('mouseup', (e) => { + if (pressStartedOnOverlay && e.target === overlay) { + shakeModal(overlay); + } + pressStartedOnOverlay = false; + }); + }); + + // Escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + const openOverlay = document.querySelector('.modal-overlay.show'); + if (openOverlay) { + e.preventDefault(); + shakeModal(openOverlay); + } + } + }); + }); + + // Wire up backdrop-click + Escape blocking for every modal-overlay + document.addEventListener('DOMContentLoaded', () => { + document.querySelectorAll('.modal-overlay').forEach(overlay => { + overlay.addEventListener('mousedown', (e) => { + // Only react if the click started on the overlay itself, + // not on the modal-box or its children + if (e.target === overlay) { + shakeModal(overlay); + } + }); + }); + + // Block Escape from closing (Bootstrap keyboard:false equivalent) + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + const openOverlay = document.querySelector('.modal-overlay.show'); + if (openOverlay) { + e.preventDefault(); + shakeModal(openOverlay); + } + } + }); + }); + // Close on backdrop click document.querySelectorAll('.modal-overlay').forEach(function (overlay) { overlay.addEventListener('click', function (e) { @@ -1467,7 +723,6 @@ }); }); - // ═══════════════════════════════════════════════════════ // Profile modal — tab switching // ═══════════════════════════════════════════════════════ diff --git a/CPRNIMS.WebApps/appsettings.json b/CPRNIMS.WebApps/appsettings.json index 74204bb..8f396f0 100644 --- a/CPRNIMS.WebApps/appsettings.json +++ b/CPRNIMS.WebApps/appsettings.json @@ -213,7 +213,7 @@ "GetInventoryReport": "api/InventoryReports/GetInventoryReport/" }, "ImageUploadSettings": { - "UploadPath": "C:\\WebApps\\wwwroot\\Content\\Images" + "UploadPath": "C:\\inetpub\\cprnims-web\\wwwroot\\Content\\Images" } } }, diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/AccountPostPut.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/AccountPostPut.js index 8702dc0..f294dc2 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/AccountPostPut.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/AccountPostPut.js @@ -1,4 +1,5 @@ -function postPutAccessRights(IsNotExist) { +let isNotExist = false; +function postPutAccessRights(IsNotExist) { loader = $('#overlay, #loader').css('z-index', 1070); const selectedItems = Object.values(selectedProductsMap); @@ -9,7 +10,7 @@ const userRightsList = selectedItems.map(item => { return { - UserAccessId: item.userAccessId, + UserAccessId: isNotExist, ContAccId: item.contAccId, AccessTypeId: item.accessTypeId, IsActive: true, diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/index.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/index.js index 12cee9a..40772ba 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/index.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/index.js @@ -1,32 +1,3 @@ -//navigate the picture -//document.addEventListener("DOMContentLoaded", function () { -// var profilePictureImage = document.getElementById("profilePictureImage"); -// var profilePictureInput = document.getElementById("profilePictureInput"); - -// // Set a default image source for the profile picture -// profilePictureImage.src = "wwwroot/Content/Images/404userImage.jpg"; - -// // Add a click event listener to the profile picture to trigger the file input -// profilePictureImage.addEventListener("click", function () { -// profilePictureInput.click(); -// }); - -// // Add a change event listener to the file input -// profilePictureInput.addEventListener("change", function () { -// var ProfilePicture = profilePictureInput.files[0]; - -// if (ProfilePicture) { -// // Display the selected image -// var imageURL = URL.createObjectURL(ProfilePicture); -// profilePictureImage.src = imageURL; -// } else { -// // No file selected, revert to the default image -// console.log("No file selected, using default image"); -// profilePictureImage.src = "wwwroot/Content/Images/404userImage.jpg"; -// } -// }); -//}); - let jsonObj = {}; function renderAccessDetailbtn(data, row) { @@ -39,144 +10,13 @@ function renderAccessDetailbtn(data, row) { return buttonsHtml; } -////function viewUserAccessNotExist() { -//// loader = $('#overlay, #loader'); -//// $('#viewUserAccessNotExist').modal('show'); -//// $('#viewUserAccessNotExist').css('z-index', 1060); -//// tableElement = $('#NotAccessDataTable'); -//// tableDestroy(tableElement); -//// var submitButton = $('#btnNotAccess'); -//// var totalSelectedLabel = $('#totalSelNotAccess'); -//// let IsNotExist = true; -//// notAccessDataTable = tableElement.DataTable({ -//// ajax: $.extend({ -//// url: '/Account/GetUserRights', -//// type: 'POST', -//// data: { UserId, IsNotExist }, -//// }, beforeComplete(loader)), -//// language: { -//// emptyTable: "No record available" -//// }, -//// initComplete: function () { -//// var api = this.api(); -//// var data = api.ajax.json(); -//// if (!data || !data.data || data.data === "No Data") { -//// $('.dataTables_empty').html("No record available"); -//// } -//// updateSubmitBtnVisib(); -//// updateSelectedCount(); -//// }, -//// columns: colAccountDetailNot, -//// responsive: true, -//// error: errorHandler -//// }); -//// function updateSubmitBtnVisib() { -//// var isEmpty = notAccessDataTable.data().length === 0; -//// submitButton.toggle(!isEmpty); -//// } -//// $('#NotAccessDataTable').on('change', '.select-NotAccess-checkbox', function () { -//// var row = $(this).closest('tr'); -//// if ($(this).prop('checked')) { -//// row.addClass('selected-row'); -//// } else { -//// row.removeClass('selected-row'); -//// } -//// updateSelectedCount(); -//// }); - -//// $('#selectAllCheckboxNotAccess').on('change', function () { -//// var isChecked = $(this).prop('checked'); -//// $('.select-NotAccess-checkbox').prop('checked', isChecked); -//// if (isChecked) { -//// $('#NotAccessDataTable tbody tr').addClass('selected-row'); -//// } else { -//// $('#NotAccessDataTable tbody tr').removeClass('selected-row'); -//// } -//// updateSelectedCount(); -//// }); -//// function updateSelectedCount() { -//// var totalSelected = $('.select-NotAccess-checkbox:checked').length; -//// totalSelectedLabel.text(totalSelected); -//// } -////} -////function viewUserAccess(data) { -//// loader = $('#overlay, #loader'); -//// $('#viewUserAccess').modal('show'); -//// $('#viewUserAccess').css('z-index', 1050); -//// tableElement = $('#AccessDataTable'); -//// tableDestroy(tableElement); -//// var submitButton = $('#btnAccess'); -//// var totalSelectedLabel = $('#totalSelAccess'); -//// UserId = data.id; -//// //CanvassId = data.canvassId; -//// $('#ua-EmailAddress').val(data.email); -//// $('#ua-FullName').val(data.fullName); -//// $('#uan-EmailAddress').val(data.email); -//// $('#uan-FullName').val(data.fullName); -//// accessDataTable = tableElement.DataTable({ -//// ajax: $.extend({ -//// url: '/Account/GetUserRights', -//// type: 'POST', -//// data: { UserId }, -//// }, beforeComplete(loader)), -//// language: { -//// emptyTable: "No record available" -//// }, -//// initComplete: function () { -//// var api = this.api(); -//// var data = api.ajax.json(); -//// if (!data || !data.data || data.data === "No Data") { -//// $('.dataTables_empty').html("No record available"); -//// } -//// updateSubmitBtnVisib(); -//// updateSelectedCount(); -//// }, -//// columns: colAccountDetail, -//// responsive: true, -//// error: errorHandler -//// }); -//// function updateSubmitBtnVisib() { -//// var isEmpty = accessDataTable.data().length === 0; -//// submitButton.toggle(!isEmpty); -//// } -//// $('#AccessDataTable').on('change', '.select-Access-checkbox', function () { -//// var row = $(this).closest('tr'); -//// if ($(this).prop('checked')) { -//// row.addClass('selected-row'); -//// } else { -//// row.removeClass('selected-row'); -//// } -//// updateSelectedCount(); -//// }); - -//// $('#selectAllCheckboxAccess').on('change', function () { -//// var isChecked = $(this).prop('checked'); -//// $('.select-Access-checkbox').prop('checked', isChecked); -//// if (isChecked) { -//// $('#AccessDataTable tbody tr').addClass('selected-row'); -//// } else { -//// $('#AccessDataTable tbody tr').removeClass('selected-row'); -//// } -//// updateSelectedCount(); -//// }); -//// function updateSelectedCount() { -//// var totalSelected = $('.select-Access-checkbox:checked').length; -//// totalSelectedLabel.text(totalSelected); -//// } -////} -////function ShowNewAccess() { -//// viewUserAccessNotExist(); -////} function showUpdateUserProfile(jsonData) { jsonObj = jsonData; - // jsonData.lockoutEnabled is a boolean value (true or false) var lockoutEnabled = jsonData.lockoutEnabled; - // Get the checkbox element by its ID var lockoutEnabledCheckbox = document.getElementById("LockoutEnabled"); - // Set the checkbox state based on the boolean value lockoutEnabledCheckbox.checked = lockoutEnabled; $("#Id").val(jsonData.Id); @@ -199,29 +39,21 @@ function showUpdateUserProfile(jsonData) { $("#UpdatedDate").val(jsonData.updatedDate); $("#CreatedDate").val(jsonData.createdDate); - // Assuming jsonData.profilePicture contains the base64-encoded image var urlContent = jsonData.url; - // Get the img element by its ID var imgElement = document.getElementById("profilePictureImage"); - // Check if urlContent is not null, undefined, or an empty string if (urlContent && urlContent.trim() !== "") { - // If not null or empty, set the src attribute of the img element to display the image imgElement.src = urlContent; } else { - // If null or empty, set the src to the default image imgElement.src = "/Content/Images/404userImage.jpg"; } - // Get the input element and label element var inputFieldUserRole = document.getElementById("PUserRole"); var labelUserRole = document.getElementById("PUserRoleLabel"); - // Initialize the label text with the initial input value labelUserRole.textContent = inputFieldUserRole.value; - // Listen for changes in the input field inputFieldUserRole.addEventListener("input", function () { labelUserRole.textContent = inputFieldUserRole.value; @@ -230,10 +62,8 @@ function showUpdateUserProfile(jsonData) { var inputField = document.getElementById("PFullName"); var label = document.getElementById("PFullNameLabel"); - // Initialize the label text with the initial input value label.textContent = inputField.value; - // Listen for changes in the input field inputField.addEventListener("input", function () { label.textContent = inputField.value; @@ -247,7 +77,6 @@ function updateUserProfile() { var loader = $('#overlay, #loader'); var userId = jsonObj.id; - // Get the file input element for the profile picture var profilePictureInput = document.getElementById("profilePictureInput"); if (profilePictureInput && profilePictureInput.files.length > 0) { @@ -256,21 +85,16 @@ function updateUserProfile() { reader.onload = function (event) { var base64Image = event.target.result; - // Include the base64Image in your JSON object var data = { // Other properties... ProfilePictureStr: base64Image }; - // Send the AJAX request sendUpdateRequest(data, loader, userId); }; - // Read the file as data URL reader.readAsDataURL(ProfilePicture); } else { - // No file selected, send the request with an empty ProfilePictureStr var data = { ProfilePictureStr: '' - // Other properties... }; sendUpdateRequest(data, loader, userId); } @@ -298,30 +122,27 @@ function sendUpdateRequest(data, loader, userId) { $.ajax({ url: '/Account/UpdateUserProfile', type: 'POST', - data: { ProfilePictureStr, userId, UserName, FullName, Company, Role, Email, PhoneNumber, NewPassword, LockoutEnabled, Address }, // Send form data including the profile picture + data: { ProfilePictureStr, userId, UserName, FullName, Company, Role, Email, PhoneNumber, NewPassword, LockoutEnabled, Address }, success: function (response) { if (response.success) { $('#updateUserProfile').modal('hide'); refreshTable(); - // Close the modal after 5 seconds + $('#UpdateMessage').modal('show'); setTimeout(function () { $('#UpdateMessage').modal('hide'); - }, 5000); // 5000 milliseconds (5 seconds) + }, 5000); refreshTable(); clearTextModal(); } else { - // User update was not successful, display the error message alert('User update failed: ' + response.response); } }, beforeSend: function () { - // Show the loader before making the AJAX request loader.show(); }, complete: function () { - // Hide the loader after the AJAX request is complete (success or error) loader.hide(); } }); @@ -363,7 +184,6 @@ function ShowModal() { $('#createNewUser').modal('show'); clearTextModal(); } -// Function to refresh the DataTable function refreshTable() { userListTable.ajax.reload(); } @@ -373,63 +193,100 @@ function clearTextModal() { document.getElementById("userName").value = ""; document.getElementById("email").value = ""; document.getElementById("password").value = ""; - // Reset the select fields to their default options document.getElementById("company").selectedIndex = 0; document.getElementById("role").selectedIndex = 0; } -// Function to create a new user + function addNewUser() { var loader = $('#overlay, #loader'); - var formData = $("#userRegistrationForm").serialize(); - $.ajax({ - url: '/Account/CreateAccount', - type: 'POST', - data: formData, // Send the form data - success: function (response) { - if (response.success) { - $('#createNewUser').modal('hide'); - $('#Message').modal('show'); - // Close the modal after 5 seconds - setTimeout(function () { - $('#Message').modal('hide'); - }, 2000); - refreshTable(); - clearTextModal(); - } else { - // User creation was not successful, display the error message - console.log('User creation failed:', response.response); - $('#createNewUser').modal('hide'); - alert('User creation failed: ' + response.response); - } - }, + var formData = { + FullName: $('#fullName').val(), + UserName: $('#userName').val(), + Company: $('#company').val(), + DepartmentId: parseInt($('#department').val(), 10), + Role: $('#role').val(), + Email: $('#email').val(), + Password: $('#password').val() + }; + showConfirmation({ + title: 'User Registration', + message: 'Are you sure you want to create? This action cannot be undone.', + type: 'warning', + confirmText: 'Yes', + cancelText: 'No' + }).then((confirmed) => { + if (confirmed) { + $.ajax({ + url: '/Account/CreateAccount', + type: 'POST', + data: formData, + success: function (response) { + if (response.success) { + $('#createNewUser').modal('hide'); + $('#Message').modal('show'); + // Close the modal after 5 seconds + setTimeout(function () { + $('#Message').modal('hide'); + }, 2000); + closeModal('modalCreate'); + refreshTable(); + clearTextModal(); + } else { + console.log('User creation failed:', response.response); + $('#createNewUser').modal('hide'); + alert('User creation failed: ' + response.response); + } + }, - beforeSend: function () { - // Show the loader before making the AJAX request - loader.show(); - }, - complete: function () { - // Hide the loader after the AJAX request is complete (success or error) - loader.hide(); + beforeSend: function () { + loader.show(); + }, + complete: function () { + loader.hide(); + } + }); } }); } -// Use this function to populate roles +//Population +function populateDepartment() { + $.ajax({ + url: "/Account/GetDepartment", + success: function (response) { + + if (response && response.data && Array.isArray(response.data)) { + var $department = $('#department'); + $department.empty(); + response.data.forEach(function (item) { + $department.append( + $('