From f841476cca911400be58e16b4995f25827adcc7f Mon Sep 17 00:00:00 2001 From: aurelio-aot Date: Wed, 27 May 2026 16:28:52 -0700 Subject: [PATCH 01/16] AB#32696: Applicant Profile - Payments Tab --- .../Payments/ApplicantPaymentDetailsDto.cs | 20 ++ .../Payments/ApplicantPaymentSummaryDto.cs | 8 + .../Payments/IApplicantPaymentsAppService.cs | 12 + .../Payments/ApplicantPaymentsAppService.cs | 72 ++++++ .../Pages/Applicants/Details.cshtml | 16 ++ .../ApplicantPaymentsViewComponent.cs | 63 +++++ .../ApplicantPaymentsViewModel.cs | 18 ++ .../ApplicantPayments/Default.cshtml | 73 ++++++ .../Components/ApplicantPayments/Default.css | 39 +++ .../Components/ApplicantPayments/Default.js | 243 ++++++++++++++++++ 10 files changed, 564 insertions(+) create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentDetailsDto.cs create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentSummaryDto.cs create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/IApplicantPaymentsAppService.cs create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/Payments/ApplicantPaymentsAppService.cs create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewComponent.cs create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewModel.cs create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.cshtml create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.css create mode 100644 applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentDetailsDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentDetailsDto.cs new file mode 100644 index 000000000..bd3812e09 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentDetailsDto.cs @@ -0,0 +1,20 @@ +using System; +using Unity.Payments.Enums; +using Unity.Payments.Suppliers; +using Volo.Abp.Application.Dtos; + +namespace Unity.GrantManager.ApplicantProfile; + +public class ApplicantPaymentDetailsDto : EntityDto +{ + public string ReferenceNumber { get; set; } = string.Empty; + public string ApplicationReferenceNo { get; set; } = string.Empty; + public Guid ApplicationId { get; set; } + public string? PaymentDate { get; set; } + public PaymentRequestStatus Status { get; set; } + public decimal Amount { get; set; } + public string? PaymentStatus { get; set; } + public string SupplierNumber { get; set; } = string.Empty; + public string SupplierName { get; set; } = string.Empty; + public SiteDto? Site { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentSummaryDto.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentSummaryDto.cs new file mode 100644 index 000000000..830146bde --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/ApplicantPaymentSummaryDto.cs @@ -0,0 +1,8 @@ +namespace Unity.GrantManager.ApplicantProfile; + +public class ApplicantPaymentSummaryDto +{ + public decimal TotalApprovedAmount { get; set; } + public decimal TotalPaidAmount { get; set; } + public decimal TotalRemainingAmount { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/IApplicantPaymentsAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/IApplicantPaymentsAppService.cs new file mode 100644 index 000000000..1d9537a66 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application.Contracts/ApplicantProfile/Payments/IApplicantPaymentsAppService.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace Unity.GrantManager.ApplicantProfile; + +public interface IApplicantPaymentsAppService : IApplicationService +{ + Task GetPaymentSummaryByApplicantIdAsync(Guid applicantId); + Task> GetPaymentListByApplicantIdAsync(Guid applicantId); +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/Payments/ApplicantPaymentsAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/Payments/ApplicantPaymentsAppService.cs new file mode 100644 index 000000000..5942eb2d9 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/ApplicantProfile/Payments/ApplicantPaymentsAppService.cs @@ -0,0 +1,72 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Unity.GrantManager.Applications; +using Unity.GrantManager.Payments; +using Unity.Modules.Shared; +using Unity.Payments.Codes; +using Unity.Payments.Enums; +using Unity.Payments.PaymentRequests; +using Volo.Abp.Features; + +namespace Unity.GrantManager.ApplicantProfile; + +[RequiresFeature(PaymentConsts.UnityPaymentsFeature)] +[Authorize] +public class ApplicantPaymentsAppService( + IApplicationRepository applicationRepository, + IPaymentRequestAppService paymentRequestAppService) : GrantManagerAppService, IApplicantPaymentsAppService +{ + [Authorize(UnitySelector.Payment.Summary.Default)] + public async Task GetPaymentSummaryByApplicantIdAsync(Guid applicantId) + { + var applications = await applicationRepository.GetByApplicantIdAsync(applicantId); + var totalApproved = applications.Sum(a => a.ApprovedAmount); + + if (applications.Count == 0) + return new ApplicantPaymentSummaryDto { TotalApprovedAmount = totalApproved }; + + var applicationIds = applications.Select(a => a.Id).ToList(); + var payments = await paymentRequestAppService.GetListByApplicationIdsAsync(applicationIds); + var totalPaid = payments + .Where(p => p.Status == PaymentRequestStatus.HistoricalPayment + || string.Equals(p.PaymentStatus?.Trim(), CasPaymentRequestStatus.FullyPaid, StringComparison.OrdinalIgnoreCase)) + .Sum(p => p.Amount); + + return new ApplicantPaymentSummaryDto + { + TotalApprovedAmount = totalApproved, + TotalPaidAmount = totalPaid, + TotalRemainingAmount = totalApproved - totalPaid + }; + } + + [Authorize(UnitySelector.Payment.PaymentList.Default)] + public async Task> GetPaymentListByApplicantIdAsync(Guid applicantId) + { + var applications = await applicationRepository.GetByApplicantIdAsync(applicantId); + + if (applications.Count == 0) return []; + + var referenceMap = applications.ToDictionary(a => a.Id, a => a.ReferenceNo); + var applicationIds = applications.Select(a => a.Id).ToList(); + var payments = await paymentRequestAppService.GetListByApplicationIdsAsync(applicationIds); + + return payments.Select(p => new ApplicantPaymentDetailsDto + { + Id = p.Id, + ReferenceNumber = p.ReferenceNumber, + ApplicationReferenceNo = referenceMap.TryGetValue(p.CorrelationId, out var refNo) ? refNo : string.Empty, + ApplicationId = p.CorrelationId, + PaymentDate = p.PaymentDate, + Status = p.Status, + Amount = p.Amount, + PaymentStatus = p.PaymentStatus, + SupplierNumber = p.SupplierNumber, + SupplierName = p.SupplierName, + Site = p.Site + }).ToList(); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml index c05bb09d0..c15d87e43 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/Applicants/Details.cshtml @@ -5,11 +5,14 @@ @using Unity.GrantManager.Web.Pages.Applicants @using Volo.Abp.AspNetCore.Mvc.UI.Layout @using Volo.Abp.Authorization.Permissions +@using Unity.Modules.Shared +@using Volo.Abp.Features @model DetailsModel @inject IStringLocalizer L @inject IPageLayout PageLayout @inject IPermissionChecker PermissionChecker +@inject IFeatureChecker FeatureChecker @{ PageLayout.Content.Title = L["Applicants"].Value; @@ -121,6 +124,19 @@ @*-------- History Section END ---------*@ + @*-------- Payments Section ---------*@ + @if (await FeatureChecker.IsEnabledAsync("Unity.Payments") && + (await PermissionChecker.IsGrantedAsync(UnitySelector.Payment.Summary.Default) || + await PermissionChecker.IsGrantedAsync(UnitySelector.Payment.PaymentList.Default))) + { + +
+ @await Component.InvokeAsync("ApplicantPayments", new { applicantId = Model.ApplicantId }) +
+
+ } + @*-------- Payments Section END ---------*@ + diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewComponent.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewComponent.cs new file mode 100644 index 000000000..21770dfde --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewComponent.cs @@ -0,0 +1,63 @@ +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Unity.GrantManager.ApplicantProfile; +using Unity.GrantManager.Payments; +using Unity.Modules.Shared; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Bundling; +using Volo.Abp.AspNetCore.Mvc.UI.Widgets; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Features; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantPayments; + +[Widget( + RefreshUrl = "Widget/ApplicantPayments/Refresh", + ScriptTypes = [typeof(ApplicantPaymentsScriptBundleContributor)], + StyleTypes = [typeof(ApplicantPaymentsStyleBundleContributor)], + AutoInitialize = true)] +public class ApplicantPaymentsViewComponent( + IApplicantPaymentsAppService applicantPaymentsAppService, + IFeatureChecker featureChecker, + IPermissionChecker permissionChecker) : AbpViewComponent +{ + public async Task InvokeAsync(Guid applicantId) + { + var emptyModel = new ApplicantPaymentsViewModel { ApplicantId = applicantId }; + + if (!await featureChecker.IsEnabledAsync(PaymentConsts.UnityPaymentsFeature)) + return View(emptyModel); + + if (!await permissionChecker.IsGrantedAsync(UnitySelector.Payment.Summary.Default)) + return View(emptyModel); + + var summary = await applicantPaymentsAppService.GetPaymentSummaryByApplicantIdAsync(applicantId); + + return View(new ApplicantPaymentsViewModel + { + ApplicantId = applicantId, + TotalApprovedAmount = summary.TotalApprovedAmount, + TotalPaidAmount = summary.TotalPaidAmount, + TotalRemainingAmount = summary.TotalRemainingAmount + }); + } +} + +public class ApplicantPaymentsScriptBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/Views/Shared/Components/ApplicantPayments/Default.js"); + context.Files.AddIfNotContains("/libs/jquery-maskmoney/dist/jquery.maskMoney.min.js"); + } +} + +public class ApplicantPaymentsStyleBundleContributor : BundleContributor +{ + public override void ConfigureBundle(BundleConfigurationContext context) + { + context.Files.AddIfNotContains("/Views/Shared/Components/ApplicantPayments/Default.css"); + } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewModel.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewModel.cs new file mode 100644 index 000000000..998a7b14a --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/ApplicantPaymentsViewModel.cs @@ -0,0 +1,18 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace Unity.GrantManager.Web.Views.Shared.Components.ApplicantPayments; + +public class ApplicantPaymentsViewModel +{ + public Guid ApplicantId { get; set; } + + [Display(Name = "Total Approved Amount")] + public decimal TotalApprovedAmount { get; set; } + + [Display(Name = "Total Paid Amount")] + public decimal TotalPaidAmount { get; set; } + + [Display(Name = "Total Remaining Amount")] + public decimal TotalRemainingAmount { get; set; } +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.cshtml new file mode 100644 index 000000000..0c9a9cdc6 --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.cshtml @@ -0,0 +1,73 @@ +@using Unity.GrantManager.Web.Views.Shared.Components.ApplicantPayments +@using Unity.Modules.Shared +@using Volo.Abp.Authorization.Permissions + +@inject IPermissionChecker PermissionChecker + +@model ApplicantPaymentsViewModel + +@{ + Layout = null; +} + + + +
+ + @* Payment Summary *@ + @if (await PermissionChecker.IsGrantedAsync(UnitySelector.Payment.Summary.Default)) + { +
+
+
Payment Summary
+
+
+
+
+ $ + +
+
+
+
+ $ + +
+
+
+
+ $ + +
+
+
+
+ } + + @* Payment List *@ + @if (await PermissionChecker.IsGrantedAsync(UnitySelector.Payment.PaymentList.Default)) + { +
+
Payment List
+
+ } +
+
+ +
+
+ +
+ +
+ + diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.css new file mode 100644 index 000000000..75879016f --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.css @@ -0,0 +1,39 @@ +.applicant-payments-summary { + border-bottom: 0.25rem solid var(--bc-colors-white-background); +} + +.applicant-payments-toolbar { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; +} + +.applicant-payments-toolbar .tbl-search { + max-width: 280px; +} + +.applicant-payments-toolbar .dynamic-buttons-div { + margin-left: auto; + position: relative; +} + +.applicant-payments-toolbar .dynamic-buttons-div .dt-button-collection { + left: auto !important; + right: 0 !important; + top: 100% !important; +} + +#ApplicantPaymentRequestListTable_wrapper { + overflow: visible !important; +} + +.applicant-payments-container .dt-container { + overflow: visible !important; +} + +#ApplicantPaymentRequestListTable_wrapper .dt-scroll-body { + max-height: clamp(180px, calc(100vh - 540px), 350px) !important; + overflow-y: auto !important; + overflow-x: auto !important; +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js new file mode 100644 index 000000000..2c6091a0f --- /dev/null +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js @@ -0,0 +1,243 @@ +$(function () { + const l = abp.localization.getResource('Payments'); + $('.unity-currency-input').maskMoney({}); + $('.unity-currency-input').each(function () { + $(this).maskMoney('mask', this.value); + }); + + const formatter = createNumberFormatter(); + let dt = $('#ApplicantPaymentRequestListTable'); + let dataTable; + const listColumns = getColumns(); + const defaultVisibleColumns = [ + 'referenceNumber', + 'applicationReferenceNo', + 'paymentDate', + 'status', + 'amount', + 'paymentStatus', + 'supplierNumber', + 'supplierName', + 'siteNumber', + ]; + + let actionButtons = [ + { + text: 'Filter', + className: 'custom-table-btn flex-none btn btn-secondary', + action: function () {}, + attr: { id: 'btn-toggle-filter-applicant-payments' }, + }, + { + extend: 'csv', + text: 'Export', + title: 'Applicant Payments', + className: 'custom-table-btn flex-none btn btn-secondary', + exportOptions: { + columns: ':visible:not(.notexport)', + orthogonal: 'fullName', + }, + }, + ]; + + let applicantId = document.getElementById('ApplicantPaymentsApplicantId').value; + let inputAction = function () { + return applicantId; + }; + + let responseCallback = function (result) { + if (result.length <= 15) { + $('.dataTables_paginate').hide(); + } + return { + recordsTotal: result.length, + recordsFiltered: result.length, + data: result, + }; + }; + + if (abp.auth.isGranted('Unity.GrantManager.ApplicationManagement.Payment.PaymentList')) { + dataTable = initializeDataTable({ + dt, + defaultVisibleColumns, + listColumns, + maxRowsPerPage: 10, + defaultSortColumn: { name: 'paymentDate', dir: 'desc' }, + dataEndpoint: + unity.grantManager.applicantProfile.applicantPayments + .getPaymentListByApplicantId, + data: inputAction, + responseCallback, + actionButtons, + serverSideEnabled: false, + pagingEnabled: true, + reorderEnabled: true, + languageSetValues: {}, + dataTableName: 'ApplicantPaymentRequestListTable', + externalFilterButtonId: 'btn-toggle-filter-applicant-payments', + dynamicButtonContainerId: 'applicantPaymentsDynamicButtonContainerId', + lengthMenu: [10, 25, 50, -1], + }); + + dataTable.externalSearch('#applicant-payments-search', { delay: 300 }); + + $('#nav-payments-tab').one('click', function () { + dataTable.columns.adjust(); + }); + } + + function getColumns() { + return [ + getPaymentIdColumn(), + getSubmissionIdColumn(), + getPaidDateColumn(), + getStatusColumn(), + getAmountColumn(), + getCasPaymentStatusColumn(), + getSupplierNumberColumn(), + getSupplierNameColumn(), + getSiteNumberColumn(), + ]; + } + + function getPaymentIdColumn() { + return { + title: 'Payment ID', + name: 'referenceNumber', + data: 'referenceNumber', + className: 'data-table-header', + index: 0, + }; + } + + function getSubmissionIdColumn() { + return { + title: 'Submission ID', + name: 'applicationReferenceNo', + data: 'applicationReferenceNo', + className: 'data-table-header', + index: 1, + render: function (data, type, row) { + if (type === 'display') { + return ( + '' + + (data || '') + + '' + ); + } + return data; + }, + }; + } + + function getPaidDateColumn() { + return { + title: 'Paid Date', + name: 'paymentDate', + data: 'paymentDate', + className: 'data-table-header', + index: 2, + render: function (data, type) { + if (type !== 'display' && type !== 'filter') return data || ''; + return data || ''; + }, + }; + } + + function getStatusColumn() { + return { + title: 'Status', + name: 'status', + data: 'status', + className: 'data-table-header', + index: 3, + render: function (data) { + let statusColor = getPaymentStatusTextColor(data); + return ( + '' + + l('Enum:PaymentRequestStatus.' + data) + + '' + ); + }, + }; + } + + function getAmountColumn() { + return { + title: 'Amount', + name: 'amount', + data: 'amount', + className: 'data-table-header currency-display', + index: 4, + render: function (data) { + return formatter.format(data); + }, + }; + } + + function getCasPaymentStatusColumn() { + return { + title: 'CAS Payment Status', + name: 'paymentStatus', + data: 'paymentStatus', + className: 'data-table-header', + index: 5, + }; + } + + function getSupplierNumberColumn() { + return { + title: 'Supplier #', + name: 'supplierNumber', + data: 'supplierNumber', + className: 'data-table-header', + index: 6, + }; + } + + function getSupplierNameColumn() { + return { + title: 'Supplier Name', + name: 'supplierName', + data: 'supplierName', + className: 'data-table-header', + index: 7, + }; + } + + function getSiteNumberColumn() { + return { + title: 'Site #', + name: 'siteNumber', + data: 'site.number', + className: 'data-table-header', + defaultContent: '', + index: 8, + }; + } + + function getPaymentStatusTextColor(status) { + switch (status) { + case 'L1Pending': + case 'L2Pending': + case 'L3Pending': + return '#053662'; + case 'L1Declined': + case 'L2Declined': + case 'L3Declined': + case 'Failed': + return '#CE3E39'; + case 'Submitted': + return '#5595D9'; + case 'Paid': + case 'HistoricalPayment': + return '#42814A'; + default: + return '#053662'; + } + } +}); From 4319403cdeedeb49713d40e3efbe9ea4241d9d38 Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Thu, 28 May 2026 09:58:09 -0700 Subject: [PATCH 02/16] [AB#32785] Fix tag menu slider overflow and height issues --- .../Pages/ConfigurationManagement/Index.css | 20 ++++++++++++ .../Settings/TagManagement/TagManagement.js | 2 -- .../src/Unity.GrantManager.Web/yarn.lock | 32 +++++++++---------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css index 0f7771ad4..b1c8cf5b1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css @@ -46,6 +46,21 @@ width: 95%; } +#tags-div.config-management { + overflow: visible; + max-height: none; +} + +#tags-div .dt-scroll-body { + overflow-y: visible !important; + max-height: none !important; +} + +#tags-div .dt-container { + max-height: none !important; + overflow-y: visible !important; +} + /* When scroll-managed components are embedded in the config container, constrain their height so the container's padding is visible at the bottom */ .config-management .scoresheet-scrollable-content, @@ -59,6 +74,11 @@ align-items: flex-start; } +.unity-app-container:has(.config-page-layout) { + height: auto; + min-height: 100%; +} + .hide { display: none !important; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js index d172cf266..46df2d8ef 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js @@ -219,8 +219,6 @@ $(function () { serverSide: false, paging: false, searching: true, - scrollCollapse: true, - scrollX: true, ordering: true, ajax: (requestData, callback, settings) => getUnifiedTagSummaryAjax(requestData, callback, settings), columnDefs: defineTagSummaryColumnDefs() diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/yarn.lock b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/yarn.lock index 16c553798..1bd868b67 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/yarn.lock +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/yarn.lock @@ -305,7 +305,7 @@ resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== -"@popperjs/core@^2.11.8", "@popperjs/core@^2.9.0": +"@popperjs/core@^2.9.0": version "2.11.8" resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== @@ -357,7 +357,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.16.0: +acorn@^8.16.0: version "8.16.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz" integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== @@ -427,7 +427,7 @@ bootstrap-select@~1.13.18: resolved "https://registry.npmjs.org/bootstrap-select/-/bootstrap-select-1.13.18.tgz" integrity sha512-V1IzK4rxBq5FrJtkzSH6RmFLFBsjx50byFbfAf8jYyXROWs7ZpprGjdHeoyq2HSsHyjJhMMwjsQhRoYAfxCGow== -bootstrap@^5.3.3, bootstrap@>=3.0.0: +bootstrap@^5.3.3: version "5.3.3" resolved "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz" integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== @@ -541,7 +541,7 @@ datatables.net-colreorder-bs5@~2.1.1: datatables.net-colreorder "2.1.2" jquery ">=1.7" -datatables.net-colreorder@~2.1.1, datatables.net-colreorder@2.1.2: +datatables.net-colreorder@2.1.2, datatables.net-colreorder@~2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/datatables.net-colreorder/-/datatables.net-colreorder-2.1.2.tgz" integrity sha512-lIsUyOt2nBm4sD2cSzDKZcIVrGgrZkh90Z2f03s8p7DYcZSfXMHAhFBrDYf9/eAK6wJnODN8EDMsrtPHfgoSXA== @@ -566,7 +566,7 @@ datatables.net-fixedheader-bs5@~4.0.6: datatables.net-fixedheader "4.0.6" jquery ">=1.7" -datatables.net-fixedheader@~4.0.6, datatables.net-fixedheader@4.0.6: +datatables.net-fixedheader@4.0.6, datatables.net-fixedheader@~4.0.6: version "4.0.6" resolved "https://registry.npmjs.org/datatables.net-fixedheader/-/datatables.net-fixedheader-4.0.6.tgz" integrity sha512-icYg/qKDpqGDrAVRWfsjt0xQdngk48R7LWkS9t8kaZFp9c4xrLFcmmPtRLgPp5/S4JHZbbsxmVkF16kscjNZjg== @@ -600,7 +600,7 @@ datatables.net-staterestore-dt@~1.4.2: datatables.net-staterestore "1.4.3" jquery ">=1.7" -datatables.net-staterestore@~1.4.2, datatables.net-staterestore@1.4.3: +datatables.net-staterestore@1.4.3, datatables.net-staterestore@~1.4.2: version "1.4.3" resolved "https://registry.npmjs.org/datatables.net-staterestore/-/datatables.net-staterestore-1.4.3.tgz" integrity sha512-XSkCHwi+MZ8C5ZbZ1qlvIdIOs8YEJX4BVOk3GUMoSIta6xD4UsKTDV0SxfJWRYsNnDQwvCibQD0yJhK4Vk4xTw== @@ -608,7 +608,7 @@ datatables.net-staterestore@~1.4.2, datatables.net-staterestore@1.4.3: datatables.net "1.11 - 2" jquery ">=1.7" -datatables.net@^2, datatables.net@^2.1.8, "datatables.net@1.11 - 2", datatables.net@2.3.8: +"datatables.net@1.11 - 2", datatables.net@2.3.8, datatables.net@^2, datatables.net@^2.1.8: version "2.3.8" resolved "https://registry.npmjs.org/datatables.net/-/datatables.net-2.3.8.tgz" integrity sha512-uhViowhlDlheAuo5a8TrkQqADsjrtGeOyvrigvr4t0+K3MyAWqClORXWAYIcN9VLX6iIX0C8O9gwJNd01hITRg== @@ -730,7 +730,7 @@ eslint-visitor-keys@^5.0.1: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz" integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== -eslint@^10.3.0, "eslint@^6.0.0 || ^7.0.0 || >=8.0.0": +eslint@^10.3.0: version "10.3.0" resolved "https://registry.npmjs.org/eslint/-/eslint-10.3.0.tgz" integrity sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw== @@ -1040,12 +1040,12 @@ jquery-validation-unobtrusive@^4.0.0: jquery "^3.6.0" jquery-validation ">=1.19" -jquery-validation@^1.21.0, jquery-validation@>=1.19: +jquery-validation@>=1.19, jquery-validation@^1.21.0: version "1.21.0" resolved "https://registry.npmjs.org/jquery-validation/-/jquery-validation-1.21.0.tgz" integrity sha512-xNot0rlUIgu7duMcQ5qb6MGkGL/Z1PQaRJQoZAURW9+a/2PGOUxY36o/WyNeP2T9R6jvWB8Z9lUVvvQWI/Zs5w== -"jquery@^1.7 || ^2.0 || ^3.1", jquery@^3.6.0, jquery@>=1.10, jquery@>=1.12.0, jquery@>=1.2.6, "jquery@>=1.5.0 <4.0", jquery@>=1.6, jquery@>=1.7, jquery@>=1.7.2, "jquery@>=3.4.0 <4.0.0", jquery@~3.7.1, "jquery@1.9.1 - 3": +jquery@>=1.10, jquery@>=1.12.0, jquery@>=1.2.6, "jquery@>=1.5.0 <4.0", jquery@>=1.6, jquery@>=1.7, jquery@>=1.7.2, "jquery@>=3.4.0 <4.0.0", jquery@^3.6.0, jquery@~3.7.1: version "3.7.1" resolved "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz" integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== @@ -1253,7 +1253,7 @@ path-key@^3.1.0: resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -popper.js@^1.16.1, popper.js@~1.16.1: +popper.js@~1.16.1: version "1.16.1" resolved "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== @@ -1369,6 +1369,11 @@ spark-md5@^2.0.2: resolved "https://registry.npmjs.org/spark-md5/-/spark-md5-2.0.2.tgz" integrity sha512-9WfT+FYBEvlrOOBEs484/zmbtSX4BlGjzXih1qIEWA1yhHbcqgcMHkiwXoWk2Sq1aJjLpcs6ZKV7JxrDNjIlNg== +string-hash@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz" + integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" @@ -1376,11 +1381,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -string-hash@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz" - integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== - sweetalert2@^11.14.1: version "11.26.17" resolved "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.26.17.tgz" From f8a880299a93de8d4203ea0e398bce718bbf0d69 Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Thu, 28 May 2026 10:44:41 -0700 Subject: [PATCH 03/16] [AB#32785] Refactor tag menu slider styles for consistency --- .../Pages/ConfigurationManagement/Index.css | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css index b1c8cf5b1..82608c825 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css @@ -51,14 +51,10 @@ max-height: none; } -#tags-div .dt-scroll-body { - overflow-y: visible !important; - max-height: none !important; -} - +#tags-div .dt-scroll-body, #tags-div .dt-container { - max-height: none !important; overflow-y: visible !important; + max-height: none !important; } /* When scroll-managed components are embedded in the config container, From 6dc7f8ef1fdb007a60efee19c323fbf5fe610165 Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Thu, 28 May 2026 10:55:24 -0700 Subject: [PATCH 04/16] [AB#32785] Consolidate tag table selectors --- .../Pages/ConfigurationManagement/Index.css | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css index 82608c825..401a5713e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css @@ -46,11 +46,7 @@ width: 95%; } -#tags-div.config-management { - overflow: visible; - max-height: none; -} - +#tags-div.config-management, #tags-div .dt-scroll-body, #tags-div .dt-container { overflow-y: visible !important; From 1b88e93ed00dbfc9d94d8d3b943805c6ebd5c4eb Mon Sep 17 00:00:00 2001 From: Andre Goncalves Date: Thu, 28 May 2026 12:19:04 -0700 Subject: [PATCH 05/16] AB#32218 split out attachments query --- .../Attachments/AttachmentAppService.cs | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs index 5e015095a..70ca1a4ad 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Attachments/AttachmentAppService.cs @@ -98,23 +98,42 @@ protected internal async Task> GetAttachmentsInternalA Expression> predicate) where T : AbstractS3Attachment { var attachmentsQuery = await repository.GetQueryableAsync(); - var people = await personUserRepository.GetQueryableAsync(); - var filteredAttachments = attachmentsQuery.Where(predicate); - var query = from attachment in filteredAttachments - join person in people on attachment.UserId equals person.Id - select new UnityAttachmentDto() - { - Id = attachment.Id, - FileName = attachment.FileName, - DisplayName = attachment.DisplayName, - S3ObjectKey = attachment.S3ObjectKey, - Time = attachment.Time, - AttachmentType = attachment.AttachmentType, - AttachedBy = person.FullName, - CreatorId = person.Id - }; - - return await query.AsSingleQuery().ToListAsync(); + + var attachments = await attachmentsQuery + .Where(predicate) + .Select(a => new + { + a.Id, + a.FileName, + a.DisplayName, + a.S3ObjectKey, + a.Time, + a.AttachmentType, + a.UserId + }) + .ToListAsync(); + + if (attachments.Count == 0) return []; + + var userIds = attachments.Select(a => a.UserId).Distinct().ToList(); + var people = await personUserRepository.GetListAsync(p => userIds.Contains(p.Id)); + var peopleById = people.ToDictionary(p => p.Id); + + return [.. attachments.Select(a => + { + var person = peopleById.GetValueOrDefault(a.UserId); + return new UnityAttachmentDto + { + Id = a.Id, + FileName = a.FileName, + DisplayName = a.DisplayName, + S3ObjectKey = a.S3ObjectKey, + Time = a.Time, + AttachmentType = a.AttachmentType, + AttachedBy = person?.FullName, + CreatorId = person?.Id + }; + })]; } public async Task GetAttachmentMetadataAsync(AttachmentType attachmentType, Guid attachmentId) From ed4b2604096d4afedfb679752a1d0c496cc4e8ad Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Thu, 28 May 2026 13:04:08 -0700 Subject: [PATCH 06/16] [AB#32773] Rename PaymentTagsInput for namespace conflict --- .../src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js | 2 +- .../Views/Shared/Components/PaymentActionBar/Default.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js index f464feb19..fd74fbbf9 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js @@ -355,5 +355,5 @@ $(function () { duplicate: false } - window.TagsInput = TagsInput; + window.PaymentTagsInput = TagsInput; }); diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentActionBar/Default.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentActionBar/Default.js index d7ab43374..be6bdff0a 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentActionBar/Default.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Views/Shared/Components/PaymentActionBar/Default.js @@ -5,7 +5,7 @@ $(function () { }); tagPaymentModal.onOpen(async function () { - let tagInput = new TagsInput({ + let tagInput = new PaymentTagsInput({ selector: 'SelectedTags', duplicate: false, max: 50 From 480b2a110672a816479a124ca03a5b89640101ff Mon Sep 17 00:00:00 2001 From: "Todosichuk, Daryl" Date: Thu, 28 May 2026 13:32:51 -0700 Subject: [PATCH 07/16] =?UTF-8?q?AB#33235=20Replace=20GH=5FAPI=5FTOKEN=20?= =?UTF-8?q?=E2=86=92=20GITHUB=5FTOKEN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/docker-build-dev.yml | 2 +- .github/workflows/docker-build-main.yml | 2 +- .github/workflows/docker-build-test.yml | 2 +- .github/workflows/manual-trigger.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-build-dev.yml b/.github/workflows/docker-build-dev.yml index be32d7f22..315d80bea 100644 --- a/.github/workflows/docker-build-dev.yml +++ b/.github/workflows/docker-build-dev.yml @@ -21,7 +21,7 @@ on: # Workflow dependencies env: TARGET_ENV: dev - GH_TOKEN: ${{secrets.GH_API_TOKEN}} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} diff --git a/.github/workflows/docker-build-main.yml b/.github/workflows/docker-build-main.yml index b146da454..e82812ba8 100644 --- a/.github/workflows/docker-build-main.yml +++ b/.github/workflows/docker-build-main.yml @@ -21,7 +21,7 @@ on: # Workflow dependencies env: TARGET_ENV: main - GH_TOKEN: ${{secrets.GH_API_TOKEN}} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} diff --git a/.github/workflows/docker-build-test.yml b/.github/workflows/docker-build-test.yml index 9728ee15d..71c63c59a 100644 --- a/.github/workflows/docker-build-test.yml +++ b/.github/workflows/docker-build-test.yml @@ -21,7 +21,7 @@ on: # Workflow dependencies env: TARGET_ENV: test - GH_TOKEN: ${{secrets.GH_API_TOKEN}} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} diff --git a/.github/workflows/manual-trigger.yml b/.github/workflows/manual-trigger.yml index c34b9e697..6c99e774c 100644 --- a/.github/workflows/manual-trigger.yml +++ b/.github/workflows/manual-trigger.yml @@ -18,7 +18,7 @@ on: type: string env: TARGET_ENV: ${{ inputs.name }} - GH_TOKEN: ${{secrets.GH_API_TOKEN}} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} From 68e2673e7e468c3085f0b8d8b808347c3383ec8d Mon Sep 17 00:00:00 2001 From: "Todosichuk, Daryl" Date: Thu, 28 May 2026 13:40:33 -0700 Subject: [PATCH 08/16] AB#33235 Switch sonarsource-scan.yml java-version distribution to temurin --- .github/workflows/sonarsource-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sonarsource-scan.yml b/.github/workflows/sonarsource-scan.yml index fd30e826d..375ac6f42 100644 --- a/.github/workflows/sonarsource-scan.yml +++ b/.github/workflows/sonarsource-scan.yml @@ -27,7 +27,7 @@ jobs: uses: actions/setup-java@v5 with: java-version: 17 - distribution: 'zulu' + distribution: 'temurin' - uses: actions/checkout@v6 with: From d53c02064fc04e5926db755b86eee550b956bf2a Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Thu, 28 May 2026 14:09:28 -0700 Subject: [PATCH 09/16] [AB#32773] Tag Input SonarQube fixes --- .../Pages/PaymentTags/PaymentTags.js | 34 ++++++++---------- .../Pages/ApplicationTags/ApplicationTags.js | 35 ++++++++----------- .../Shared/Components/ActionBar/Default.js | 2 +- 3 files changed, 29 insertions(+), 42 deletions(-) diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js index fd74fbbf9..7064cf163 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js @@ -51,7 +51,6 @@ $(function () { this.arr.push({ Id: id, Name: tagText }); - let tagInput = this; let tag = document.createElement('span'); tag.className = this.options.tagClass + ' ' + tagClass; @@ -65,9 +64,9 @@ $(function () { e.preventDefault(); let tag = this.parentNode; - let tagIndex = Array.from(tagInput.wrapper.childNodes).indexOf(tag); + let tagIndex = Array.from(this.wrapper.childNodes).indexOf(tag); if (tagIndex !== -1) { - tagInput.deleteTag(tag, tagIndex); + this.deleteTag(tag, tagIndex); } }) @@ -82,23 +81,21 @@ $(function () { } TagsInput.prototype.deleteTag = function (tag, i) { - let self = this; - - if (this.arr[i] && this.arr[i].Name === 'Uncommon Tags') { + if (this.arr[i]?.Name === 'Uncommon Tags') { abp.message.confirm('Are you sure you want to delete all the uncommon tags?') .then(function (confirmed) { if (confirmed) { tag.remove(); - self.arr.splice(i, 1); - self.orignal_input.value = JSON.stringify(self.arr); - updateSelectedTagsInput(self.arr); + this.arr.splice(i, 1); + this.orignal_input.value = JSON.stringify(this.arr); + updateSelectedTagsInput(this.arr); // Expand input if no tags remain - if (self.arr.length === 0) { - self.input.classList.add('expanded'); + if (this.arr.length === 0) { + this.input.classList.add('expanded'); } - return self; + return this; } }); } else { @@ -134,10 +131,8 @@ $(function () { } TagsInput.prototype.addData = function (array) { - let plugin = this; - array.forEach(function (string) { - plugin.addTag(string); + this.addTag(string); }) return this; } @@ -154,14 +149,13 @@ $(function () { this.orignal_input.removeAttribute('hidden'); delete this.orignal_input; - let self = this; Object.keys(this).forEach(function (key) { - if (self[key] instanceof HTMLElement) - self[key].remove(); + if (this[key] instanceof HTMLElement) + this[key].remove(); if (key != 'options') - delete self[key]; + delete this[key]; }); this.initialized = false; @@ -355,5 +349,5 @@ $(function () { duplicate: false } - window.PaymentTagsInput = TagsInput; + globalThis.PaymentTagsInput = TagsInput; }); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js index 1d537c479..98d51fabf 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js @@ -51,8 +51,6 @@ $(function () { this.arr.push({ Id: id, Name: tagText }); - let tagInput = this; - let tag = document.createElement('span'); tag.className = this.options.tagClass + ' ' + tagClass; tag.innerText = tagText; @@ -65,9 +63,9 @@ $(function () { e.preventDefault(); let tag = this.parentNode; - let tagIndex = Array.from(tagInput.wrapper.childNodes).indexOf(tag); + let tagIndex = Array.from(this.wrapper.childNodes).indexOf(tag); if (tagIndex !== -1) { - tagInput.deleteTag(tag, tagIndex); + this.deleteTag(tag, tagIndex); } }) @@ -82,23 +80,21 @@ $(function () { } TagsInput.prototype.deleteTag = function (tag, i) { - let self = this; - - if (this.arr[i] && this.arr[i].Name === 'Uncommon Tags') { + if (this.arr[i]?.Name === 'Uncommon Tags') { abp.message.confirm('Are you sure you want to delete all the uncommon tags?') .then(function (confirmed) { if (confirmed) { tag.remove(); - self.arr.splice(i, 1); - self.orignal_input.value = JSON.stringify(self.arr); - updateSelectedTagsInput(self.arr); + this.arr.splice(i, 1); + this.orignal_input.value = JSON.stringify(this.arr); + updateSelectedTagsInput(this.arr); // Expand input if no tags remain - if (self.arr.length === 0) { - self.input.classList.add('expanded'); + if (this.arr.length === 0) { + this.input.classList.add('expanded'); } - return self; + return this; } }); } else { @@ -134,10 +130,8 @@ $(function () { } TagsInput.prototype.addData = function (array) { - let plugin = this; - array.forEach(function (string) { - plugin.addTag(string); + this.addTag(string); }) return this; } @@ -154,14 +148,13 @@ $(function () { this.orignal_input.removeAttribute('hidden'); delete this.orignal_input; - let self = this; Object.keys(this).forEach(function (key) { - if (self[key] instanceof HTMLElement) - self[key].remove(); + if (this[key] instanceof HTMLElement) + this[key].remove(); if (key != 'options') - delete self[key]; + delete this[key]; }); this.initialized = false; @@ -353,5 +346,5 @@ $(function () { duplicate: false } - window.TagsInput = TagsInput; + globalThis.TagsInput = TagsInput; }); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ActionBar/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ActionBar/Default.js index 4cbdd8650..4ba8e589c 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ActionBar/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ActionBar/Default.js @@ -218,7 +218,7 @@ $(function () { userTagsInput.setSuggestions(suggestionsArray); userTagsInput.addData(tagInputArray); - document.getElementById("user-tags-input").setAttribute("data-touched", "false"); + document.getElementById("user-tags-input").dataset.touched = "false"; }); tagApplicationModal.onResult(function () { abp.notify.success( From e8a561397b6b8a1e674a62c451fce08ceb91d02e Mon Sep 17 00:00:00 2001 From: Velang Date: Thu, 28 May 2026 14:36:42 -0700 Subject: [PATCH 10/16] initial commit --- .../Unity.AutoUI/cypress/support/commands.ts | 214 ++++++++++-------- 1 file changed, 122 insertions(+), 92 deletions(-) diff --git a/applications/Unity.AutoUI/cypress/support/commands.ts b/applications/Unity.AutoUI/cypress/support/commands.ts index 7216c2766..07edc350b 100644 --- a/applications/Unity.AutoUI/cypress/support/commands.ts +++ b/applications/Unity.AutoUI/cypress/support/commands.ts @@ -143,15 +143,39 @@ Cypress.Commands.add("getChefsDetail", (key: string) => { Cypress.Commands.add("chefsLogin", () => { cy.getChefsDetail("chefsBaseURL").then((baseURL) => { cy.visit(baseURL); // Visit the URL fetched from chefs.json - cy.get("#app > div > main > header > header > div > div.d-print-none") - .should("exist") - .click(); // click the login button + cy.get("body").then(($body) => { + // Prefer resilient text-based selectors over brittle full DOM paths. + if ($body.find("button:contains('LOGIN'), a:contains('LOGIN')").length) { + cy.contains("button, a", /^LOGIN$/i) + .first() + .click({ force: true }); + } else if ( + $body.find( + "#app > div > main > header > header > div > div.d-print-none", + ).length + ) { + cy.get("#app > div > main > header > header > div > div.d-print-none") + .should("exist") + .click({ force: true }); + } + }); cy.wait(1000); - cy.get( - "#app > div > main > div.v-container.v-locale--is-ltr.text-center.main > div > div:nth-child(2) > div > button", - ) - .should("exist") - .click(); // click the idir buttton + cy.get("body").then(($body) => { + // Some pages show an IDIR choice button before the credential form. + if ($body.find("button:contains('IDIR'), a:contains('IDIR')").length) { + cy.contains("button, a", /IDIR/i).first().click({ force: true }); + } else if ( + $body.find( + "#app > div > main > div.v-container.v-locale--is-ltr.text-center.main > div > div:nth-child(2) > div > button", + ).length + ) { + cy.get( + "#app > div > main > div.v-container.v-locale--is-ltr.text-center.main > div > div:nth-child(2) > div > button", + ) + .should("exist") + .click({ force: true }); + } + }); cy.wait(1000); cy.get("body").then(($body) => { // Check if you're already logged in. @@ -246,11 +270,14 @@ function fetchGrantApplications(): Cypress.Chainable { .then((response) => { if (response.status !== 200) { throw new Error( - `API request failed with status ${response.status}: ${JSON.stringify(response.body)}` + `API request failed with status ${response.status}: ${JSON.stringify(response.body)}`, ); } const data = response.body as GrantApplicationResponse; - Cypress.log({ name: "fetch", message: `📋 Fetched ${data.items?.length || 0} applications` }); + Cypress.log({ + name: "fetch", + message: `📋 Fetched ${data.items?.length || 0} applications`, + }); return data.items || []; }); }); @@ -262,89 +289,92 @@ Cypress.Commands.add( return fetchGrantApplications().then((allApplications) => { let applications = allApplications; - Cypress.log({ name: "fetch", message: `📋 Fetched ${applications.length} applications from API` }); - - // Filter by category if specified (e.g., 'Data Seeder') - if (options.categoryFilter) { - applications = applications.filter((app) => - app.category === options.categoryFilter - ); - Cypress.log({ - name: "filter", - message: `📋 Filtered to ${applications.length} applications with category: ${options.categoryFilter}`, - }); - } - - // Filter by status if specified (e.g., 'Submitted', 'Under Assessment', 'Approved') - if (options.statusFilter && options.statusFilter.length > 0) { - applications = applications.filter((app) => - options.statusFilter!.includes(app.status) - ); - Cypress.log({ - name: "filter", - message: `📋 Filtered to ${applications.length} applications with status: ${options.statusFilter.join(", ")}`, - }); - } - - // Filter by max age if specified - if (options.maxAge) { - const cutoffDate = new Date(); - cutoffDate.setDate(cutoffDate.getDate() - options.maxAge); - applications = applications.filter((app) => { - const submissionDate = new Date(app.submissionDate); - return submissionDate >= cutoffDate; - }); - Cypress.log({ - name: "filter", - message: `📋 Filtered to ${applications.length} applications within ${options.maxAge} days`, - }); - } - - if (applications.length === 0) { - throw new Error( - "No applications found matching the specified criteria" - ); - } - - // Sort applications (default: by submissionDate descending for latest first) - const sortBy = options.sortBy || 'submissionDate'; - const sortOrder = options.sortOrder || 'desc'; - applications.sort((a, b) => { - let aVal: number | string; - let bVal: number | string; - - if (sortBy === 'submissionDate') { - aVal = new Date(a.submissionDate).getTime(); - bVal = new Date(b.submissionDate).getTime(); - } else { - aVal = a[sortBy] as number; - bVal = b[sortBy] as number; - } - - if (sortOrder === 'desc') { - return bVal > aVal ? 1 : bVal < aVal ? -1 : 0; - } else { - return aVal > bVal ? 1 : aVal < bVal ? -1 : 0; - } - }); - - // Get the submission at the specified index (default: 0 = first/latest) - const index = options.index || 0; - if (index >= applications.length) { - throw new Error( - `Index ${index} out of range. Only ${applications.length} applications available.` - ); - } - - const selectedApp = applications[index]; - Cypress.log({ - name: "selected", - message: `✅ Selected submission: ${selectedApp.referenceNo} (Status: ${selectedApp.status}, Category: ${selectedApp.category})`, - }); - - return selectedApp.referenceNo; + Cypress.log({ + name: "fetch", + message: `📋 Fetched ${applications.length} applications from API`, + }); + + // Filter by category if specified (e.g., 'Data Seeder') + if (options.categoryFilter) { + applications = applications.filter( + (app) => app.category === options.categoryFilter, + ); + Cypress.log({ + name: "filter", + message: `📋 Filtered to ${applications.length} applications with category: ${options.categoryFilter}`, + }); + } + + // Filter by status if specified (e.g., 'Submitted', 'Under Assessment', 'Approved') + if (options.statusFilter && options.statusFilter.length > 0) { + applications = applications.filter((app) => + options.statusFilter!.includes(app.status), + ); + Cypress.log({ + name: "filter", + message: `📋 Filtered to ${applications.length} applications with status: ${options.statusFilter.join(", ")}`, + }); + } + + // Filter by max age if specified + if (options.maxAge) { + const cutoffDate = new Date(); + cutoffDate.setDate(cutoffDate.getDate() - options.maxAge); + applications = applications.filter((app) => { + const submissionDate = new Date(app.submissionDate); + return submissionDate >= cutoffDate; }); - } + Cypress.log({ + name: "filter", + message: `📋 Filtered to ${applications.length} applications within ${options.maxAge} days`, + }); + } + + if (applications.length === 0) { + throw new Error( + "No applications found matching the specified criteria", + ); + } + + // Sort applications (default: by submissionDate descending for latest first) + const sortBy = options.sortBy || "submissionDate"; + const sortOrder = options.sortOrder || "desc"; + applications.sort((a, b) => { + let aVal: number | string; + let bVal: number | string; + + if (sortBy === "submissionDate") { + aVal = new Date(a.submissionDate).getTime(); + bVal = new Date(b.submissionDate).getTime(); + } else { + aVal = a[sortBy] as number; + bVal = b[sortBy] as number; + } + + if (sortOrder === "desc") { + return bVal > aVal ? 1 : bVal < aVal ? -1 : 0; + } else { + return aVal > bVal ? 1 : aVal < bVal ? -1 : 0; + } + }); + + // Get the submission at the specified index (default: 0 = first/latest) + const index = options.index || 0; + if (index >= applications.length) { + throw new Error( + `Index ${index} out of range. Only ${applications.length} applications available.`, + ); + } + + const selectedApp = applications[index]; + Cypress.log({ + name: "selected", + message: `✅ Selected submission: ${selectedApp.referenceNo} (Status: ${selectedApp.status}, Category: ${selectedApp.category})`, + }); + + return selectedApp.referenceNo; + }); + }, ); /** From 14fe289ed9dcb4320f3d404aea061e74e6037fd7 Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Thu, 28 May 2026 15:29:57 -0700 Subject: [PATCH 11/16] [AB#32773] Refactor event listeners to use arrow functions --- .../Pages/PaymentTags/PaymentTags.js | 10 +++++----- .../Pages/ApplicationTags/ApplicationTags.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js index 7064cf163..0b9325eab 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentTags/PaymentTags.js @@ -60,9 +60,9 @@ $(function () { let closeIcon = document.createElement('a'); closeIcon.innerHTML = '×'; - closeIcon.addEventListener('click', function (e) { + closeIcon.addEventListener('click', (e) => { e.preventDefault(); - let tag = this.parentNode; + let tag = e.currentTarget.parentNode; let tagIndex = Array.from(this.wrapper.childNodes).indexOf(tag); if (tagIndex !== -1) { @@ -83,7 +83,7 @@ $(function () { TagsInput.prototype.deleteTag = function (tag, i) { if (this.arr[i]?.Name === 'Uncommon Tags') { abp.message.confirm('Are you sure you want to delete all the uncommon tags?') - .then(function (confirmed) { + .then((confirmed) => { if (confirmed) { tag.remove(); this.arr.splice(i, 1); @@ -131,7 +131,7 @@ $(function () { } TagsInput.prototype.addData = function (array) { - array.forEach(function (string) { + array.forEach((string) => { this.addTag(string); }) return this; @@ -150,7 +150,7 @@ $(function () { delete this.orignal_input; - Object.keys(this).forEach(function (key) { + Object.keys(this).forEach((key) => { if (this[key] instanceof HTMLElement) this[key].remove(); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js index 98d51fabf..c560de278 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTags.js @@ -59,9 +59,9 @@ $(function () { let closeIcon = document.createElement('a'); closeIcon.innerHTML = '×'; - closeIcon.addEventListener('click', function (e) { + closeIcon.addEventListener('click', (e) => { e.preventDefault(); - let tag = this.parentNode; + let tag = e.currentTarget.parentNode; let tagIndex = Array.from(this.wrapper.childNodes).indexOf(tag); if (tagIndex !== -1) { @@ -82,7 +82,7 @@ $(function () { TagsInput.prototype.deleteTag = function (tag, i) { if (this.arr[i]?.Name === 'Uncommon Tags') { abp.message.confirm('Are you sure you want to delete all the uncommon tags?') - .then(function (confirmed) { + .then((confirmed) => { if (confirmed) { tag.remove(); this.arr.splice(i, 1); @@ -130,7 +130,7 @@ $(function () { } TagsInput.prototype.addData = function (array) { - array.forEach(function (string) { + array.forEach((string) => { this.addTag(string); }) return this; @@ -149,7 +149,7 @@ $(function () { delete this.orignal_input; - Object.keys(this).forEach(function (key) { + Object.keys(this).forEach((key) => { if (this[key] instanceof HTMLElement) this[key].remove(); From 2bee95310333c27dbd65d2c7282a8a2b66f7e2f2 Mon Sep 17 00:00:00 2001 From: Velang Date: Thu, 28 May 2026 16:54:44 -0700 Subject: [PATCH 12/16] AB#33254 Fix chefs smoke test to validate pre-auth DOM only --- .../cypress/e2e/library/chefs.cy.ts | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/applications/Unity.AutoUI/cypress/e2e/library/chefs.cy.ts b/applications/Unity.AutoUI/cypress/e2e/library/chefs.cy.ts index 67900ba15..c2867af2c 100644 --- a/applications/Unity.AutoUI/cypress/e2e/library/chefs.cy.ts +++ b/applications/Unity.AutoUI/cypress/e2e/library/chefs.cy.ts @@ -1,8 +1,17 @@ -describe('Chefs Login and Logout', () => { +describe("Chefs Login and Logout", () => { + it("Verify that Chefs is online.", () => { + cy.getChefsDetail("chefsBaseURL").then((baseURL) => { + cy.visit(baseURL); - it('Verify that Chefs is online.', () => { - cy.chefsLogin(); - cy.contains("My Forms").should('exist').click(); - cy.chefsLogout(); - }) -}) \ No newline at end of file + cy.contains("button, a, [role='button']", /log\s*in|login/i) + .should("exist") + .click({ force: true }); + + cy.location("pathname").should("include", "/app/login"); + cy.contains("button, a, [role='button']", /IDIR/i).should("exist"); + cy.contains("button, a, [role='button']", /BC Services Card/i).should( + "exist", + ); + }); + }); +}); From c768f2af218d34df066187598fb93f493bd1b9fc Mon Sep 17 00:00:00 2001 From: aurelio-aot Date: Thu, 28 May 2026 17:44:40 -0700 Subject: [PATCH 13/16] AB#32696: Fix bug on export button --- .../Views/Shared/Components/ApplicantPayments/Default.js | 1 + 1 file changed, 1 insertion(+) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js index 2c6091a0f..84c59f5c5 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js @@ -34,6 +34,7 @@ $(function () { title: 'Applicant Payments', className: 'custom-table-btn flex-none btn btn-secondary', exportOptions: { + rows: { search: 'applied' }, columns: ':visible:not(.notexport)', orthogonal: 'fullName', }, From 86a855e504632c6970e2a3c3c1378e98e5426044 Mon Sep 17 00:00:00 2001 From: aurelio-aot Date: Thu, 28 May 2026 17:56:57 -0700 Subject: [PATCH 14/16] AB#32696: Fix sonarqube issues --- .../Components/ApplicantPayments/Default.js | 216 +++++++++--------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js index 84c59f5c5..b5d6d4e66 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantPayments/Default.js @@ -1,3 +1,111 @@ +function getPaymentIdColumn() { + return { + title: 'Payment ID', + name: 'referenceNumber', + data: 'referenceNumber', + className: 'data-table-header', + index: 0, + }; +} + +function getSubmissionIdColumn() { + return { + title: 'Submission ID', + name: 'applicationReferenceNo', + data: 'applicationReferenceNo', + className: 'data-table-header', + index: 1, + render: function (data, type, row) { + if (type === 'display') { + return ( + '' + + (data || '') + + '' + ); + } + return data; + }, + }; +} + +function getPaidDateColumn() { + return { + title: 'Paid Date', + name: 'paymentDate', + data: 'paymentDate', + className: 'data-table-header', + index: 2, + render: function (data, type) { + if (type !== 'display' && type !== 'filter') return data || ''; + return data || ''; + }, + }; +} + +function getCasPaymentStatusColumn() { + return { + title: 'CAS Payment Status', + name: 'paymentStatus', + data: 'paymentStatus', + className: 'data-table-header', + index: 5, + }; +} + +function getSupplierNumberColumn() { + return { + title: 'Supplier #', + name: 'supplierNumber', + data: 'supplierNumber', + className: 'data-table-header', + index: 6, + }; +} + +function getSupplierNameColumn() { + return { + title: 'Supplier Name', + name: 'supplierName', + data: 'supplierName', + className: 'data-table-header', + index: 7, + }; +} + +function getSiteNumberColumn() { + return { + title: 'Site #', + name: 'siteNumber', + data: 'site.number', + className: 'data-table-header', + defaultContent: '', + index: 8, + }; +} + +function getPaymentStatusTextColor(status) { + switch (status) { + case 'L1Pending': + case 'L2Pending': + case 'L3Pending': + return '#053662'; + case 'L1Declined': + case 'L2Declined': + case 'L3Declined': + case 'Failed': + return '#CE3E39'; + case 'Submitted': + return '#5595D9'; + case 'Paid': + case 'HistoricalPayment': + return '#42814A'; + default: + return '#053662'; + } +} + $(function () { const l = abp.localization.getResource('Payments'); $('.unity-currency-input').maskMoney({}); @@ -101,52 +209,6 @@ $(function () { ]; } - function getPaymentIdColumn() { - return { - title: 'Payment ID', - name: 'referenceNumber', - data: 'referenceNumber', - className: 'data-table-header', - index: 0, - }; - } - - function getSubmissionIdColumn() { - return { - title: 'Submission ID', - name: 'applicationReferenceNo', - data: 'applicationReferenceNo', - className: 'data-table-header', - index: 1, - render: function (data, type, row) { - if (type === 'display') { - return ( - '' + - (data || '') + - '' - ); - } - return data; - }, - }; - } - - function getPaidDateColumn() { - return { - title: 'Paid Date', - name: 'paymentDate', - data: 'paymentDate', - className: 'data-table-header', - index: 2, - render: function (data, type) { - if (type !== 'display' && type !== 'filter') return data || ''; - return data || ''; - }, - }; - } - function getStatusColumn() { return { title: 'Status', @@ -179,66 +241,4 @@ $(function () { }, }; } - - function getCasPaymentStatusColumn() { - return { - title: 'CAS Payment Status', - name: 'paymentStatus', - data: 'paymentStatus', - className: 'data-table-header', - index: 5, - }; - } - - function getSupplierNumberColumn() { - return { - title: 'Supplier #', - name: 'supplierNumber', - data: 'supplierNumber', - className: 'data-table-header', - index: 6, - }; - } - - function getSupplierNameColumn() { - return { - title: 'Supplier Name', - name: 'supplierName', - data: 'supplierName', - className: 'data-table-header', - index: 7, - }; - } - - function getSiteNumberColumn() { - return { - title: 'Site #', - name: 'siteNumber', - data: 'site.number', - className: 'data-table-header', - defaultContent: '', - index: 8, - }; - } - - function getPaymentStatusTextColor(status) { - switch (status) { - case 'L1Pending': - case 'L2Pending': - case 'L3Pending': - return '#053662'; - case 'L1Declined': - case 'L2Declined': - case 'L3Declined': - case 'Failed': - return '#CE3E39'; - case 'Submitted': - return '#5595D9'; - case 'Paid': - case 'HistoricalPayment': - return '#42814A'; - default: - return '#053662'; - } - } }); From c10cfd3fcb9f97b9a266a8df8ac86f64ce626ed7 Mon Sep 17 00:00:00 2001 From: Patrick <135162612+plavoie-BC@users.noreply.github.com> Date: Fri, 29 May 2026 07:42:24 -0700 Subject: [PATCH 15/16] [AB#32773] Update modal save button based on permissions --- .../ApplicationTagsSelectionModal.cshtml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTagsSelectionModal.cshtml b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTagsSelectionModal.cshtml index 8e848d840..4db55d8ef 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTagsSelectionModal.cshtml +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationTags/ApplicationTagsSelectionModal.cshtml @@ -1,7 +1,6 @@ @page @using Newtonsoft.Json @using Unity.Modules.Shared -@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal @using Volo.Abp.Authorization.Permissions @model Unity.GrantManager.Web.Pages.ApplicationTags.ApplicationTagsModalModel @@ -49,7 +48,14 @@ } - + @if (await PermissionChecker.IsGrantedAsync(UnitySelector.Application.Tags.Create) || await PermissionChecker.IsGrantedAsync(UnitySelector.Application.Tags.Delete)) + { + + } + else + { + + } From 4ee794861cc1fe8da7c980cf3f9246a2405aeacf Mon Sep 17 00:00:00 2001 From: "Todosichuk, Daryl" Date: Fri, 29 May 2026 07:48:24 -0700 Subject: [PATCH 16/16] AB#33235 Apply token GH_API_TOKEN at PushVariables job level --- .github/workflows/docker-build-dev.yml | 2 +- .github/workflows/docker-build-main.yml | 2 +- .github/workflows/docker-build-test.yml | 2 +- .github/workflows/manual-trigger.yml | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-build-dev.yml b/.github/workflows/docker-build-dev.yml index 315d80bea..be32d7f22 100644 --- a/.github/workflows/docker-build-dev.yml +++ b/.github/workflows/docker-build-dev.yml @@ -21,7 +21,7 @@ on: # Workflow dependencies env: TARGET_ENV: dev - GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + GH_TOKEN: ${{secrets.GH_API_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} diff --git a/.github/workflows/docker-build-main.yml b/.github/workflows/docker-build-main.yml index e82812ba8..b146da454 100644 --- a/.github/workflows/docker-build-main.yml +++ b/.github/workflows/docker-build-main.yml @@ -21,7 +21,7 @@ on: # Workflow dependencies env: TARGET_ENV: main - GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + GH_TOKEN: ${{secrets.GH_API_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} diff --git a/.github/workflows/docker-build-test.yml b/.github/workflows/docker-build-test.yml index 71c63c59a..9728ee15d 100644 --- a/.github/workflows/docker-build-test.yml +++ b/.github/workflows/docker-build-test.yml @@ -21,7 +21,7 @@ on: # Workflow dependencies env: TARGET_ENV: test - GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + GH_TOKEN: ${{secrets.GH_API_TOKEN}} OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }} OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }} OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} diff --git a/.github/workflows/manual-trigger.yml b/.github/workflows/manual-trigger.yml index 6c99e774c..3761bd180 100644 --- a/.github/workflows/manual-trigger.yml +++ b/.github/workflows/manual-trigger.yml @@ -89,6 +89,8 @@ jobs: permissions: actions: write contents: read + env: + GH_TOKEN: ${{ secrets.GH_API_TOKEN }} steps: - name: Checkout repository uses: actions/checkout@v6