Skip to content
Merged

Dev #2661

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ec8a414
AB#33530 initial commit for tenant details edit
AndreGAot Jul 6, 2026
0b60338
[AB#33559] Add Bulk Publish Service Endpoints
plavoie-BC Jul 8, 2026
0b51fcd
Merge remote-tracking branch 'origin/dev' into feature/AB#33530-tenan…
AndreGAot Jul 8, 2026
b7bc5ae
[AB#33559] Add bulk publish to action bar
plavoie-BC Jul 8, 2026
44b7438
[AB#33559] Add Status Visible column to Applications DataTable
plavoie-BC Jul 9, 2026
8260c68
[AB#33559] Add publish filter to GetApplicationsForBulkPublish
plavoie-BC Jul 9, 2026
a677e69
[AB#33559] Add BulkPublishApplications Modal
plavoie-BC Jul 9, 2026
b4f1a0f
AB#33530 program area metadata configuration
AndreGAot Jul 9, 2026
715cfdf
[AB#33559] Build Fixes
plavoie-BC Jul 9, 2026
0ed6cf7
Apply suggestions from code review
AndreGAot Jul 9, 2026
45ab75d
AB#33530 code review fixes
AndreGAot Jul 9, 2026
4af03aa
[AB#33559] Implement bulk publish modal functionality
plavoie-BC Jul 10, 2026
e15d73c
AB#33530 extract Program Details into its own application service
AndreGAot Jul 10, 2026
eb38200
[AB#33769] Publish button and notification text update
plavoie-BC Jul 10, 2026
63f0950
[AB#33567] Modular permission to publish and bulk publish status
plavoie-BC Jul 10, 2026
153234f
[AB#33567] Add authorization for Publish UI elements
plavoie-BC Jul 10, 2026
99cb77a
Merge pull request #2651 from bcgov/feature/AB#33530-tenant-configura…
AndreGAot Jul 10, 2026
e5412e7
Merge remote-tracking branch 'origin/dev' into feature/AB#33559-bulk-…
plavoie-BC Jul 10, 2026
8c2f3b3
[AB#33559] Bulk Publish Code Quality Fixes
plavoie-BC Jul 10, 2026
ec0d42f
[AB#33559] Move bulk publish methods to ApplicationBulkActionService
plavoie-BC Jul 10, 2026
606766f
[AB#33559] Update Permission Labels
plavoie-BC Jul 10, 2026
399b392
[AB#33559] Code Quality Cleanup
plavoie-BC Jul 10, 2026
871fe19
AB#33530 add missing divider
AndreGAot Jul 10, 2026
9db54f7
Merge pull request #2658 from bcgov/feature/AB#33530-tenant-configura…
AndreGAot Jul 10, 2026
51e0017
[AB#33665] Fix Form Mapping Page Dropdowns
plavoie-BC Jul 10, 2026
3db52ae
[AB#33660] Fix Applicant Details FYE Control Styling
plavoie-BC Jul 10, 2026
7cf221c
Merge pull request #2659 from bcgov/bugfix/AB#33665-general-bugfixes
JamesPasta Jul 10, 2026
837cd06
Merge pull request #2656 from bcgov/feature/AB#33559-bulk-publish
JamesPasta Jul 10, 2026
a10784f
feature/AB#32580-TemplateAttachments-FixIssues
JamesPasta Jul 10, 2026
5a30239
Merge pull request #2660 from bcgov/feature/AB#32580-TemplateAttachments
JamesPasta Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;


namespace Unity.Notifications.EmailGroups
Expand All @@ -11,6 +12,7 @@ public interface IEmailGroupUsersAppService
Task<bool> DeleteUserAsync (Guid id);
Task<bool> DeleteUsersByGroupIdAsync (Guid id);
Task<bool> DeleteUsersByUserIdAsync(Guid id);
[AllowAnonymous]
Task<List<EmailGroupUsersDto>> GetEmailGroupUsersByGroupIdAsync(Guid id);
Task<List<EmailGroupUsersDto>> GetListAsync();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;


namespace Unity.Notifications.EmailGroups
Expand All @@ -10,6 +11,7 @@ public interface IEmailGroupsAppService
Task<EmailGroupDto> CreateAsync (EmailGroupDto dto);
Task<EmailGroupDto> UpdateAsync (EmailGroupDto dto);
Task<bool> DeleteAsync (Guid id);
[AllowAnonymous]
Task<List<EmailGroupDto>> GetListAsync();
Task<EmailGroupDto> GetEmailGroupByIdAsync(Guid id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ public override void Define(IPermissionDefinitionContext context)
NotificationsPermissions.Email.ScheduleCreate,
L($"Permission:{NotificationsPermissions.Email.ScheduleCreate}"));

scheduleNotificationsPermissions.AddChild(
NotificationsPermissions.Email.ScheduleDelete,
L($"Permission:{NotificationsPermissions.Email.ScheduleDelete}"));

scheduleNotificationsPermissions.AddChild(
NotificationsPermissions.Email.ScheduleCancel,
L($"Permission:{NotificationsPermissions.Email.ScheduleCancel}"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public static class Email
public const string Schedule = "Notifications.Email.Schedule";
public const string NotificationsTab = "Notifications.Form.Tab";
public const string ScheduleCreate = "Notifications.Form.Email.Schedule.Create";
public const string ScheduleDelete = "Notifications.Form.Email.Schedule.Delete";
public const string ScheduleCancel = "Notifications.Form.Email.Schedule.Cancel";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public async Task<bool> DeleteUsersByGroupIdAsync(Guid id)
}
}

[AllowAnonymous]
public async Task<List<EmailGroupUsersDto>> GetEmailGroupUsersByGroupIdAsync(Guid id)
{
var users = await _emailGroupUsersRepository.GetListAsync(u => u.GroupId == id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public EmailGroupsAppService(IEmailGroupsRepository emailGroupsRepository)
_emailGroupsRepository = emailGroupsRepository;
}
public async Task<EmailGroupDto> CreateAsync(EmailGroupDto dto)
{
{
var newGroup = await _emailGroupsRepository.InsertAsync(new EmailGroup
{
Name = dto.Name,
Expand All @@ -42,7 +42,7 @@ public async Task<EmailGroupDto> UpdateAsync(EmailGroupDto dto)
var emailGroup = await _emailGroupsRepository.GetAsync(dto.Id, true);
emailGroup.Name = dto.Name;
emailGroup.Description = dto.Description;
emailGroup.Type = dto.Type;
emailGroup.Type = dto.Type;
await _emailGroupsRepository.UpdateAsync(emailGroup, autoSave: true);
return new EmailGroupDto
{
Expand All @@ -66,9 +66,10 @@ public async Task<bool> DeleteAsync(Guid id)
}
}

[AllowAnonymous]
public async Task<List<EmailGroupDto>> GetListAsync()
{
var groups = await _emailGroupsRepository.GetListAsync();
var groups = await _emailGroupsRepository.GetListAsync();
return ObjectMapper.Map<List<EmailGroup>, List<EmailGroupDto>>(groups);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@

<!-- Email Templates -->
<div class="tab-pane fade" id="nav-template" role="tabpanel" aria-labelledby="nav-template-tab">
<input type="hidden" id="Extensions" value="@Model.Extensions" />
<input type="hidden" id="MaxFileSize" value="@Model.MaxFileSize" />
<input type="hidden" id="EmailAttachmentMaxFileSize" value="@Model.EmailAttachmentMaxFileSize" />
<input type="hidden" id="TotalEmailAttachmentMaxFileSize" value="@Model.TotalEmailAttachmentMaxFileSize" />

<div class="row">
@await Html.PartialAsync("/Views/Settings/NotificationsSettingGroup/_Templates.cshtml")
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,4 +428,9 @@ textarea {
position: relative;
margin-left: -20px;
transform: translateX(-10px);
}

button.btn.fullWidth:hover {
background-color: #ffffff !important;
color: #000000 !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ $(function () {
if (templatesDataTable) {
templatesDataTable.columns.adjust();
}
if (emailAttachmentsTable) {
emailAttachmentsTable.columns.adjust();
}
}

function closeRightPanel() {
Expand Down Expand Up @@ -222,6 +225,13 @@ $(function () {
UiElements.deleteButton.show();
$('#email-attachments-section').show();
initEmailAttachmentsTable(data.id);

// Recalculate table columns after initialization
if (emailAttachmentsTable) {
setTimeout(() => {
emailAttachmentsTable.columns.adjust().draw();
}, 100);
}
}

function populateFieldsForNewTemplate() {
Expand Down Expand Up @@ -703,6 +713,9 @@ $(function () {
return;
}

// Ensure table has 100% width
$('#EmailAttachmentsTable').css('width', '100%');

emailAttachmentsTable = $('#EmailAttachmentsTable').DataTable(
abp.libs.datatables.normalizeConfiguration({
serverSide: false,
Expand All @@ -721,24 +734,17 @@ $(function () {
),
columnDefs: [
{
title: '<i class="fl fl-paperclip"></i>',
width: '40px',
className: 'text-center',
orderable: false,
render: function () {
return '<i class="fl fl-paperclip"></i>';
}
},
{
targets: 0,
title: 'Document Name',
data: 'fileName',
className: 'data-table-header text-break',
className: 'data-table-header text-break text-start',
width: '40%'
},
{
targets: 1,
title: 'Date',
data: 'time',
className: 'data-table-header',
className: 'data-table-header text-start',
width: '130px',
render: function (data, type) {
if (type === 'display' || type === 'filter') {
Expand All @@ -748,15 +754,17 @@ $(function () {
}
},
{
targets: 2,
title: 'Attached by',
data: 'attachedBy',
className: 'data-table-header',
className: 'data-table-header text-start',
width: '25%'
},
{
targets: 3,
title: 'File Size',
data: 'fileSize',
className: 'data-table-header',
className: 'data-table-header text-start',
width: '90px',
render: function (data) {
if (!data) return '—';
Expand All @@ -765,17 +773,21 @@ $(function () {
}
},
{
title: '',
targets: 4,
title: 'Actions',
data: 'id',
width: '80px',
className: 'text-center',
className: 'text-start',
orderable: false,
render: function (data) {
return generateEmailAttachmentButtonContent(data);
}
}
],
drawCallback: function () {
if (emailAttachmentsTable) {
emailAttachmentsTable.columns.adjust();
}
}
})
);
Expand Down Expand Up @@ -928,13 +940,23 @@ $(function () {

$leftPane.css('flex', `0 0 ${leftPct}%`);
$rightPane.css({ 'flex': 'none', 'width': rightPct + '%' });

// Recalculate table columns while dragging
if (emailAttachmentsTable) {
emailAttachmentsTable.columns.adjust();
}
});

$(document).on('mouseup.splitDrag', function () {
if (isDragging) {
isDragging = false;
$divider.removeClass('dragging');
$('body').removeClass('split-dragging');

// Final recalculation after dragging completes
if (emailAttachmentsTable) {
emailAttachmentsTable.columns.adjust().draw();
}
}
});
}
Expand Down Expand Up @@ -1047,7 +1069,7 @@ function createMenuItems(dropdownItems, editor) {
* @returns {string} HTML for attachment button
*/
function generateEmailAttachmentButtonContent(attachmentId) {
return `<button class="btn fullWidth" style="margin:10px" type="button" onclick="deleteEmailAttachment('${attachmentId}')">
return `<button class="btn fullWidth btn btn-action-gray" style="margin:10px" type="button" onclick="deleteEmailAttachment('${attachmentId}')">
<i class="fl fl-cancel"></i>
</button>`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,39 @@
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Widgets;
using Volo.Abp.Settings;

using Microsoft.Extensions.Configuration;
namespace Unity.Notifications.Web.Views.Settings.NotificationsSettingGroup;

[Widget(
ScriptTypes = [typeof(NotificationsSettingScriptBundleContributor)],
StyleTypes = [typeof(NotificationsSettingStyleBundleContributor)],
AutoInitialize = true
)]
public class NotificationsSettingViewComponent(ISettingProvider settingProvider) : AbpViewComponent
public class NotificationsSettingViewComponent(ISettingProvider settingProvider,
IConfiguration configuration) : AbpViewComponent
{
public virtual async Task<IViewComponentResult> InvokeAsync()
{
string retryMaxSetting = await settingProvider.GetOrNullAsync(Notifications.Settings.NotificationsSettings.Mailing.EmailMaxRetryAttempts) ?? "3";
var success = int.TryParse(retryMaxSetting, out int maximumRetryAttempts);
if (!success) { maximumRetryAttempts = 3; }



var model = new NotificationsSettingViewModel
{
DefaultFromAddress = await settingProvider.GetOrNullAsync(Notifications.Settings.NotificationsSettings.Mailing.DefaultFromAddress) ?? "",
MaximumRetryAttempts = maximumRetryAttempts,
EnableEmailDelay = string.Equals(
await settingProvider.GetOrNullAsync(Notifications.Settings.NotificationsSettings.Mailing.EnableEmailDelay),
"true", System.StringComparison.OrdinalIgnoreCase)
"true", System.StringComparison.OrdinalIgnoreCase),
Extensions = configuration["S3:DisallowedFileTypes"] ?? "",
MaxFileSize = configuration["S3:MaxFileSize"] ?? "",
EmailAttachmentMaxFileSize = configuration["S3:EmailAttachmentMaxFileSize"] ?? "",
TotalEmailAttachmentMaxFileSize = configuration["S3:EmailAttachmentsTotalMaxFileSize"] ?? "25"
};


return View("~/Views/Settings/NotificationsSettingGroup/Default.cshtml", model);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ public class NotificationsSettingViewModel

[Display(Name = "Enable Email Delay")]
public bool EnableEmailDelay { get; set; }

public string Extensions { get; set; } = string.Empty;
public string MaxFileSize { get; set; } = string.Empty;
public string EmailAttachmentMaxFileSize { get; set; } = string.Empty;
public string TotalEmailAttachmentMaxFileSize { get; set; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,4 @@
</div>
</div>
</div>


<input type="hidden" id="Extensions" value="[ &quot;exe&quot; , &quot;sh&quot; , &quot;ksh&quot; , &quot;bat&quot; , &quot;cmd&quot; ]">
<input type="hidden" id="MaxFileSize" value="25">
<input type="hidden" id="EmailAttachmentMaxFileSize" value="20">
<input type="hidden" id="TotalEmailAttachmentMaxFileSize" value="25">
<input type="hidden" id="EmailId" value="">


</div>
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,15 @@ public static partial class Update
}
}
}

public static partial class Application
{
public static partial class Status
{
public const string Default = "Unity.GrantManager.ApplicationManagement.Application.Status";
public const string Publish = "Unity.GrantManager.ApplicationManagement.Application.Status.Publish";
public const string Unpublish = "Unity.GrantManager.ApplicationManagement.Application.Status.Unpublish";
public const string BulkPublish = "Unity.GrantManager.ApplicationManagement.Application.Status.BulkPublish";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class ApplicantTenantDto
{
public Guid TenantId { get; set; }
public string TenantName { get; set; } = string.Empty;
public Dictionary<string, string> Metadata { get; set; } = [];
public string? DisplayName { get; set; }
public string? DefaultFromAddress { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.GrantManager.GrantApplications;
using Volo.Abp.Application.Services;

namespace Unity.GrantManager.Applications
Expand All @@ -13,6 +14,8 @@ public interface IApplicationBulkActionsAppService : IApplicationService
/// <param name="input">Request containing list of application IDs</param>
/// <returns>Cache key to retrieve the stored IDs</returns>
Task<StoreApplicationIdsResultDto> StoreApplicationIdsAsync(StoreApplicationIdsRequestDto input);
Task<List<BulkPublishDto>> GetApplicationsForBulkPublish(Guid[] applicationGuids, bool excludePublished = true);
Task BulkPublishApplications(Guid[] applicationGuids);
}

public class StoreApplicationIdsRequestDto
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;

namespace Unity.GrantManager.GrantApplications;

public class BulkPublishDto
{
public BulkPublishDto()
{
ReferenceNo = string.Empty;
ApplicantName = string.Empty;
FormName = string.Empty;
ApplicationStatus = string.Empty;
}

public Guid ApplicationId { get; set; }
public string ReferenceNo { get; set; }
public string ApplicantName { get; set; }
public string FormName { get; set; }
public DateTime? FinalDecisionDate { get; set; }
public string ApplicationStatus { get; set; }
public bool ExternalStatusVisibility { get; set; }
public string ExternalStatus { get; set; } = string.Empty;
public string PublishedStatus { get; set; } = string.Empty;
}
Loading
Loading