Skip to content

Feature/ab#28192 Tenant Configuration Management Menu #2333

Merged
JamesPasta merged 2 commits into
devfrom
feature/AB#28192-tenant-configuration-management-menu
Apr 22, 2026
Merged

Feature/ab#28192 Tenant Configuration Management Menu #2333
JamesPasta merged 2 commits into
devfrom
feature/AB#28192-tenant-configuration-management-menu

Conversation

@DavidBrightBcGov
Copy link
Copy Markdown
Contributor

New Configuration Menu that merges multiple configurations into a single location. Primarily uses invoking components from their original location where possible.

New Configuration Menu that merges multiple configurations into a single location. Primarily uses invoking components from their original location where possible.
@github-actions
Copy link
Copy Markdown

🧪 Unit Test Results (Parallel Execution)

Tests

📊 Summary

Result Count
✅ Passed 620
❌ Failed 0
⚠️ Skipped 0

📄 HTML Reports

  • Merged Tests (HTML): Included in artifacts
    Generated automatically by CI.

@DavidBrightBcGov DavidBrightBcGov marked this pull request as ready for review April 22, 2026 20:18
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

🧪 Unit Test Results (Parallel Execution)

Tests

📊 Summary

Result Count
✅ Passed 620
❌ Failed 0
⚠️ Skipped 0

📄 HTML Reports

  • Merged Tests (HTML): Included in artifacts
    Generated automatically by CI.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a consolidated Configuration Management page to centralize multiple tenant configuration areas (Notifications, Payments, Flex configs, Tags, AI) and updates existing components/scripts so they can be invoked from this new location.

Changes:

  • Introduces /ConfigurationManagement Razor Page with side-menu navigation, shared layout styling, and section visibility controlled by feature/permission flags.
  • Moves script/style loading responsibilities from embedded setting component views into bundling/page-level includes to support reuse.
  • Adapts Flex preview components to support new preview container IDs and adds local JS/CSS copies for configuration subpages.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagementViewComponent.cshtml Removes inline script include from Tag Management widget view.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Settings/TagManagement/TagManagement.js Defers permission checks/modal initialization to document-ready.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/ScoresheetConfiguration.js Adds page-local Scoresheet configuration script for the consolidated page.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/PaymentConfigurations.js Adds page-local Payments configuration script (DataTables + modals + prefix update).
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/PaymentConfigurations.css Adds page-local Payments configuration styling.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/NotificationSettings.css Adds page-local notification styling (currently unreferenced).
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.js Implements side-menu navigation, section switching, DataTables adjustment, resizable splits.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.css Adds consolidated page layout + resizable split + preview styling.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.cshtml.cs Adds Configuration Management page model with feature/permission-driven visibility flags and payment config loading.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ConfigurationManagement/Index.cshtml Adds consolidated configuration page UI and bundles/scripts/styles for embedded components.
applications/Unity.GrantManager/src/Unity.GrantManager.Web/Menus/GrantManagerMenus.cs Adds ConfigurationManagement menu constant.
applications/Unity.GrantManager/src/Unity.GrantManager.Domain.Shared/Localization/GrantManager/en.json Adds localization for the new menu entry and normalizes formatting in the touched section.
applications/Unity.GrantManager/modules/Unity.Theme.UX2/src/Unity.Theme.UX2/Themes/UX2/Components/Topbar/Default.cshtml Replaces multiple config links with a single Configuration Management link and removes Settings link.
applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/NotificationsSettingViewComponent.cs Ensures InternalEmailGroups JS is included via the widget bundle contributor.
applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.cshtml Removes inline script/style includes from the Notifications settings view.
applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/WorksheetListWidget/WorksheetList.js Supports alternate preview container id (#worksheet-preview) and scopes readonly input selection.
applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/Scoresheet/Scoresheet.js Supports alternate preview container id (#scoresheet-preview).
applications/Unity.GrantManager/modules/Unity.AI/src/Unity.AI.Web/Views/Settings/AISettingGroup/Default.cshtml Removes inline script include from AI settings view.

Comment on lines +1 to +73
.v-scroll {
max-height: 600px;
overflow-y: auto;
padding-right: 10px;
scroll-behavior: smooth;
}

.tui-editor-body {
min-height: 250px;
}

.note-text {
font-size: 12px;
}

/* Group Users Table - Push remove button to far right */
#groupUsersTable td:last-child,
#createGroupUsersTable td:last-child {
text-align: right !important;
}

#groupUsersTable th:last-child,
#createGroupUsersTable th:last-child {
width: 30px !important;
min-width: 30px !important;
max-width: 30px !important;
}

/* Fix DataTable empty message positioning */
#groupUsersTable td.dataTables_empty,
#createGroupUsersTable td.dataTables_empty,
#groupUsersTable td.dt-empty,
#createGroupUsersTable td.dt-empty {
text-align: center !important;
}

/* Ensure table maintains proper width */
#createGroupUsersTable {
width: 100% !important;
}

/* Add User Button Styling */
.btn-add-user {
background-color: white !important;
border: 2px solid var(--bs-primary) !important;
color: var(--bs-primary) !important;
font-weight: 700;
padding: 0.25rem 0.5rem;
white-space: nowrap;
transition: all 0.15s ease-in-out;
border-radius: 4px;
font-size: 0.875rem;
}

.btn-add-user:hover:not(:disabled) {
background-color: var(--bs-primary) !important;
color: white !important;
}

.btn-add-user:disabled {
opacity: 0.5;
cursor: not-allowed;
border-color: var(--bs-secondary) !important;
color: var(--bs-secondary) !important;
}

.btn-add-user i {
font-size: 0.8rem;
}

.modal-footer {
margin-top: 10px;
}
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This stylesheet appears to be unused: there are no references to /Pages/ConfigurationManagement/NotificationSettings.css in the repository. If these styles are needed for the Configuration Management notifications section, add it to the page’s style bundle; otherwise remove the file to avoid dead/duplicated CSS that will be hard to maintain.

Suggested change
.v-scroll {
max-height: 600px;
overflow-y: auto;
padding-right: 10px;
scroll-behavior: smooth;
}
.tui-editor-body {
min-height: 250px;
}
.note-text {
font-size: 12px;
}
/* Group Users Table - Push remove button to far right */
#groupUsersTable td:last-child,
#createGroupUsersTable td:last-child {
text-align: right !important;
}
#groupUsersTable th:last-child,
#createGroupUsersTable th:last-child {
width: 30px !important;
min-width: 30px !important;
max-width: 30px !important;
}
/* Fix DataTable empty message positioning */
#groupUsersTable td.dataTables_empty,
#createGroupUsersTable td.dataTables_empty,
#groupUsersTable td.dt-empty,
#createGroupUsersTable td.dt-empty {
text-align: center !important;
}
/* Ensure table maintains proper width */
#createGroupUsersTable {
width: 100% !important;
}
/* Add User Button Styling */
.btn-add-user {
background-color: white !important;
border: 2px solid var(--bs-primary) !important;
color: var(--bs-primary) !important;
font-weight: 700;
padding: 0.25rem 0.5rem;
white-space: nowrap;
transition: all 0.15s ease-in-out;
border-radius: 4px;
font-size: 0.875rem;
}
.btn-add-user:hover:not(:disabled) {
background-color: var(--bs-primary) !important;
color: white !important;
}
.btn-add-user:disabled {
opacity: 0.5;
cursor: not-allowed;
border-color: var(--bs-secondary) !important;
color: var(--bs-secondary) !important;
}
.btn-add-user i {
font-size: 0.8rem;
}
.modal-footer {
margin-top: 10px;
}
/* Unused stylesheet content removed. If Notification Settings still requires page-specific
styles, add this file to the page's style bundle and reintroduce only the selectors that
are actively used by the page. */

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +57
@if (CurrentUser.IsInRole("system_admin") && await FeatureChecker.IsEnabledAsync("SettingManagement.Enable"))
{
<abp-dropdown-item href="/ScoresheetConfiguration">Scoresheets Configuration</abp-dropdown-item>
<abp-dropdown-item href="/WorksheetConfiguration">Custom Fields Configuration</abp-dropdown-item>
<abp-dropdown-item href="/ConfigurationManagement">Configuration Management</abp-dropdown-item>
}
@if (CurrentUser.IsInRole("ITOperations"))
{
<abp-dropdown-item href="/UnityAdmin">Unity Admin</abp-dropdown-item>
}
@if (CurrentUser.IsInRole("system_admin") && await FeatureChecker.IsEnabledAsync("SettingManagement.Enable"))
{
<abp-dropdown-item href="/SettingManagement">Settings</abp-dropdown-item>
}

Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The topbar no longer links to /SettingManagement. The new Configuration Management page does not include all existing Setting Management groups (e.g., the Background Jobs settings group), so removing this link makes those settings effectively unreachable through the UI. Either keep the Settings entry in the dropdown, or add the missing Setting Management groups into Configuration Management so functionality isn’t lost.

Copilot uses AI. Check for mistakes.
{
<abp-script src="/Pages/ConfigurationManagement/PaymentConfigurations.js" />
}
<abp-script src="/Pages/ConfigurationManagement/ScoresheetConfiguration.js" />
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScoresheetConfiguration.js is included unconditionally, even when the Scoresheets section is not rendered. This script wires up PubSub subscriptions and DOM updates (e.g., scoresheet-info-widget) and can throw runtime errors if the element isn’t present. Make this script include conditional on Model.ShowScoresheets (similar to Payments/Notifications) to avoid executing scoresheet-only logic on tenants where Scoresheets is hidden/disabled.

Suggested change
<abp-script src="/Pages/ConfigurationManagement/ScoresheetConfiguration.js" />
@if (Model.ShowScoresheets)
{
<abp-script src="/Pages/ConfigurationManagement/ScoresheetConfiguration.js" />
}

Copilot uses AI. Check for mistakes.
Comment on lines +62 to +92
<li id="notifications-menu-item" class="nav-item btn btn-nav" data-target="notifications-div">
Notifications
</li>
}
@if (Model.ShowPayments)
{
<li id="payments-menu-item" class="nav-item btn btn-nav" data-target="payments-div">
Payments
</li>
}
@if (Model.ShowCustomFields)
{
<li id="custom-fields-menu-item" class="nav-item btn btn-nav" data-target="custom-fields-div">
Custom Fields
</li>
}
@if (Model.ShowScoresheets)
{
<li id="scoresheets-menu-item" class="nav-item btn btn-nav" data-target="scoresheets-div">
Scoresheets
</li>
}
@if (Model.ShowTags)
{
<li id="tags-menu-item" class="nav-item btn btn-nav" data-target="tags-div">
Tags
</li>
}
@if (Model.ShowAI)
{
<li id="ai-menu-item" class="nav-item btn btn-nav" data-target="ai-div">
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The side menu items are rendered as clickable <li> elements with only a click handler. <li> isn’t keyboard-focusable by default, so this breaks keyboard navigation/screen reader interaction. Use <button>/<a> elements for menu actions, or add role="button", tabindex="0", and key handlers (Enter/Space) to meet accessibility requirements.

Suggested change
<li id="notifications-menu-item" class="nav-item btn btn-nav" data-target="notifications-div">
Notifications
</li>
}
@if (Model.ShowPayments)
{
<li id="payments-menu-item" class="nav-item btn btn-nav" data-target="payments-div">
Payments
</li>
}
@if (Model.ShowCustomFields)
{
<li id="custom-fields-menu-item" class="nav-item btn btn-nav" data-target="custom-fields-div">
Custom Fields
</li>
}
@if (Model.ShowScoresheets)
{
<li id="scoresheets-menu-item" class="nav-item btn btn-nav" data-target="scoresheets-div">
Scoresheets
</li>
}
@if (Model.ShowTags)
{
<li id="tags-menu-item" class="nav-item btn btn-nav" data-target="tags-div">
Tags
</li>
}
@if (Model.ShowAI)
{
<li id="ai-menu-item" class="nav-item btn btn-nav" data-target="ai-div">
<li id="notifications-menu-item" class="nav-item btn btn-nav" data-target="notifications-div" role="button" tabindex="0" onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.click(); }">
Notifications
</li>
}
@if (Model.ShowPayments)
{
<li id="payments-menu-item" class="nav-item btn btn-nav" data-target="payments-div" role="button" tabindex="0" onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.click(); }">
Payments
</li>
}
@if (Model.ShowCustomFields)
{
<li id="custom-fields-menu-item" class="nav-item btn btn-nav" data-target="custom-fields-div" role="button" tabindex="0" onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.click(); }">
Custom Fields
</li>
}
@if (Model.ShowScoresheets)
{
<li id="scoresheets-menu-item" class="nav-item btn btn-nav" data-target="scoresheets-div" role="button" tabindex="0" onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.click(); }">
Scoresheets
</li>
}
@if (Model.ShowTags)
{
<li id="tags-menu-item" class="nav-item btn btn-nav" data-target="tags-div" role="button" tabindex="0" onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.click(); }">
Tags
</li>
}
@if (Model.ShowAI)
{
<li id="ai-menu-item" class="nav-item btn btn-nav" data-target="ai-div" role="button" tabindex="0" onkeydown="if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.click(); }">

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +37
const splitRestoreMap = {
'custom-fields-div': initResizableSplit('worksheet-split-container', 'worksheet-left', 'worksheet-divider', 'worksheet-right', 'worksheetSplitWidth'),
'scoresheets-div': initResizableSplit('scoresheet-split-container', 'scoresheet-left', 'scoresheet-divider', 'scoresheet-right', 'scoresheetSplitWidth')
};
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

splitRestoreMap is initialized after init() has already auto-selected and shown the first section. As a result, saved split widths won’t be restored for the initially displayed section until the user clicks away/back. Consider constructing splitRestoreMap before calling init(), or after auto-selecting the first section explicitly invoke the appropriate restore function when applicable.

Copilot uses AI. Check for mistakes.
Comment on lines +112 to +113
disableColumnSelect: true,
externalSearchId: 'search-data-table'
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PaymentSettingsDataTable is configured to use the external search input #search-data-table, but that search box only exists in the Account Coding tab. This means Payment Settings can end up filtered by a hidden input, and the user can’t see or clear the active filter while on the Payment Settings tab. Consider disabling external search for this table (omit externalSearchId) or adding a Payment Settings search input and using a different ID.

Suggested change
disableColumnSelect: true,
externalSearchId: 'search-data-table'
disableColumnSelect: true

Copilot uses AI. Check for mistakes.
</label>
</abp-column>
</abp-row>
<div class="btn-group" id="app_custom_buttons">
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page renders multiple elements with the same id="app_custom_buttons" (one in the Account Coding tab and another in the Payment Settings tab). Duplicate IDs are invalid HTML and can cause selectors (and any scripts/plugins relying on #app_custom_buttons) to behave unpredictably. Use unique IDs per tab or remove the id if it’s not required.

Suggested change
<div class="btn-group" id="app_custom_buttons">
<div class="btn-group" id="payment_settings_custom_buttons">

Copilot uses AI. Check for mistakes.
@JamesPasta JamesPasta merged commit aceee6d into dev Apr 22, 2026
25 checks passed
@JamesPasta JamesPasta deleted the feature/AB#28192-tenant-configuration-management-menu branch April 24, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants