diff --git a/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts b/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts index 52c129791a..5dc10d1b41 100644 --- a/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts +++ b/applications/Unity.AutoUI/cypress/pages/ApplicationsListPage.ts @@ -338,7 +338,7 @@ export class ApplicationsListPage extends ApplicationsPage { const titles: string[] = Cypress.$($els) .toArray() .map((el: HTMLElement) => - (el.textContent || "").replace(/\s+/g, " ").trim(), + (el.textContent || "").replaceAll(/\s+/g, " ").trim(), ) .filter((t: string) => t.length > 0); return titles; diff --git a/applications/Unity.AutoUI/cypress/pages/ListPages.ts b/applications/Unity.AutoUI/cypress/pages/ListPages.ts index 5cdf7cdb2a..4694e43a88 100644 --- a/applications/Unity.AutoUI/cypress/pages/ListPages.ts +++ b/applications/Unity.AutoUI/cypress/pages/ListPages.ts @@ -543,8 +543,8 @@ export class ApplicationsPage extends ListPage { .find(`td:nth-child(${this.columns.requestedAmount + 1})`) .text() .trim(); - const amount = Number.parseFloat(amountText.replace(/[$,]/g, "")); - if (!isNaN(amount)) { + const amount = Number.parseFloat(amountText.replaceAll(/[$,]/g, "")); + if (!Number.isNaN(amount)) { total += amount; } }) diff --git a/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts b/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts index afe702025e..9e58c6ddeb 100644 --- a/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts +++ b/applications/Unity.AutoUI/cypress/regression/ApprovalFlow.cy.ts @@ -639,7 +639,7 @@ const APPLICATIONS_PATH = "GrantApplications"; // Skip gracefully if the supplier has no site data in this environment cy.get("body").then(($body) => { const rows = $body.find("#SiteInfoTable tbody tr"); - const firstRowText = rows.first().text().replace(/\s+/g, " ").trim(); + const firstRowText = rows.first().text().replaceAll(/\s+/g, " ").trim(); const hasTokenError = $body.text().includes("GetAuthTokenAsync") || $body.text().includes("Error retrieving Token"); diff --git a/applications/Unity.AutoUI/cypress/utilities/TestDataHelper.ts b/applications/Unity.AutoUI/cypress/utilities/TestDataHelper.ts index 25b02c39e2..cfa55d6aa8 100644 --- a/applications/Unity.AutoUI/cypress/utilities/TestDataHelper.ts +++ b/applications/Unity.AutoUI/cypress/utilities/TestDataHelper.ts @@ -81,7 +81,7 @@ export class TestDataHelper { * Parse currency string to number */ static parseCurrency(currencyString: string): number { - return Number.parseFloat(currencyString.replace(/[$,]/g, "")); + return Number.parseFloat(currencyString.replaceAll(/[$,]/g, "")); } /** diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/ScoresheetConfiguration/ScoresheetModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/ScoresheetConfiguration/ScoresheetModal.cshtml index c2f3e98ce8..feea3f3f00 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/ScoresheetConfiguration/ScoresheetModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/ScoresheetConfiguration/ScoresheetModal.cshtml @@ -69,6 +69,6 @@ let src = $('#scoresheetTitle'); let dest = $('#scoresheetName'); let name = src.val().toLowerCase().trim() + '-v1'; - dest.val(name.replace(/\s+/g, "")); + dest.val(name.replaceAll(/\s+/g, "")); } \ No newline at end of file diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertSectionModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertSectionModal.cshtml index d03969aa7f..b1f3eeb3d8 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertSectionModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertSectionModal.cshtml @@ -98,7 +98,7 @@ function onNumberInput(value) { let clamped = Number.parseInt(value, 10); - if (isNaN(clamped)) clamped = 0; + if (Number.isNaN(clamped)) clamped = 0; clamped = Math.min(100, Math.max(0, clamped)); document.getElementById('FieldWidth').value = clamped; document.getElementById('FieldColumns').value = widthToColumns(clamped); diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertWorksheetModal.cshtml b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertWorksheetModal.cshtml index dca05d5ee9..ce512dbe02 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertWorksheetModal.cshtml +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Pages/WorksheetConfiguration/UpsertWorksheetModal.cshtml @@ -49,7 +49,7 @@ let src = $('#worksheetTitle'); let dest = $('#worksheetName'); let name = src.val().toLowerCase().trim() + '-v1'; - dest.val(name.replace(/\s+/g, "")); + dest.val(name.replaceAll(/\s+/g, "")); } function deleteWorksheet() { diff --git a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js index ba2d1bcb57..4435d2db64 100644 --- a/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js +++ b/applications/Unity.GrantManager/modules/Unity.Flex/src/Unity.Flex.Web/Views/Shared/Components/DataGridWidget/Default.js @@ -42,7 +42,7 @@ function calculateDatagridColumnSum(table, columnIndex) { let total = 0; table.column(columnIndex).data().each(function (value) { // Remove currency symbols and commas for numeric check - let cleanedValue = value.replace(/[^\d.-]/g, ''); + let cleanedValue = value.replaceAll(/[^\d.-]/g, ''); if (isDatagridCellNumeric(cleanedValue)) { total += Number.parseFloat(cleanedValue); } diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatusModal.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatusModal.js index 1c54e8d999..134986984c 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatusModal.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentApprovals/UpdatePaymentRequestStatusModal.js @@ -48,7 +48,7 @@ function closePaymentModal() { } function checkMaxValue(applicationId, input, amountRemaining) { - let enteredValue = Number.parseFloat(input.value.replace(/,/g, "")); + let enteredValue = Number.parseFloat(input.value.replaceAll(',', "")); let remainingErrorId = "#column_" + applicationId + "_remaining_error"; if (amountRemaining < enteredValue) { $(remainingErrorId).css("display", "block"); @@ -113,7 +113,7 @@ function calculateUpdateTotalAmount() { let total = 0; $('.amount').each(function () { // Remove commas and $ symbols before parsing - let rawValue = $(this).val().replace(/[$,]/g, ''); + let rawValue = $(this).val().replaceAll(/[$,]/g, ''); let value = Number.parseFloat(rawValue) || 0; total += value; this.value = upatePaymentNumberFormatter.format(value); diff --git a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js index e3a185a23c..6a11c45d51 100644 --- a/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js +++ b/applications/Unity.GrantManager/modules/Unity.Payments/src/Unity.Payments.Web/Pages/PaymentRequests/CreatePaymentRequestsModal.js @@ -57,7 +57,7 @@ function checkMaxValueRequest(applicationId, input, amountRemaining) { validateParentChildAmounts(applicationId); } else { // Use existing remaining amount validation - let enteredValue = Number.parseFloat(input.value.replace(/,/g, '')); + let enteredValue = Number.parseFloat(input.value.replaceAll(',', '')); let remainingErrorId = '#error_column_' + applicationId; if (amountRemaining < enteredValue) { $(remainingErrorId).css('display', 'block'); @@ -94,7 +94,7 @@ function validateAllPaymentAmounts() { ).val() ); let enteredValue = - Number.parseFloat(amountInput.val().replace(/,/g, '')) || 0; + Number.parseFloat(amountInput.val().replaceAll(',', '')) || 0; let remainingErrorId = `#error_column_${correlationId}`; if (enteredValue > remainingAmount) { @@ -127,7 +127,7 @@ function submitPayments() { function calculateTotalAmount() { let total = 0; $('.amount').each(function () { - let value = Number.parseFloat($(this).val().replace(/,/g, '')) || 0; + let value = Number.parseFloat($(this).val().replaceAll(',', '')) || 0; total += value; }); @@ -170,7 +170,7 @@ function formatCurrency(value) { const numericValue = typeof value === 'number' ? value - : Number.parseFloat(String(value ?? '').replace(/,/g, '')); + : Number.parseFloat(String(value ?? '').replaceAll(',', '')); return cadFormatter.format( Number.isFinite(numericValue) ? numericValue : 0 ); @@ -231,7 +231,7 @@ function validateParentChildAmounts(correlationId) { let amountInput = $( `input[name="ApplicationPaymentRequestForm[${itemIndex}].Amount"]` ); - let amount = Number.parseFloat(amountInput.val().replace(/,/g, '')) || 0; + let amount = Number.parseFloat(amountInput.val().replaceAll(',', '')) || 0; groupTotal += amount; } }); diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Reconciliation/Index.js b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Reconciliation/Index.js index 9df2bf0a7f..e38cc30cb5 100644 --- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Reconciliation/Index.js +++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Reconciliation/Index.js @@ -38,8 +38,8 @@ $(function () { let filtered_submissions = submissions.filter(x => x.tenant.toLowerCase().includes($('#ReconciliationTenantFilter').val().toLowerCase()) && - (isNaN(dateTo.getTime()) || new Date(x.createdAt) <= dateTo) && - (isNaN(dateFrom.getTime()) || new Date(x.createdAt) >= dateFrom) && + (Number.isNaN(dateTo.getTime()) || new Date(x.createdAt) <= dateTo) && + (Number.isNaN(dateFrom.getTime()) || new Date(x.createdAt) >= dateFrom) && (x.category == $("#ReconciliationCategoryFilter").val() || $("#ReconciliationCategoryFilter").val() == "all") ); diff --git a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js index 3b7b834ed4..105d8d3afe 100644 --- a/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js +++ b/applications/Unity.GrantManager/modules/Unity.TenantManagement/src/Unity.TenantManagement.Web/Pages/TenantManagement/Tenants/Index.js @@ -191,7 +191,7 @@ function _renderFeatureItem(feature) { let id = 'ft-' + feature.name.replaceAll('.', '-'); - let checked = feature.value === 'true' ? ' checked' : ''; + let checked = (feature.value || '').toLowerCase() === 'true' ? ' checked' : ''; return '
' + '' + @@ -270,7 +270,7 @@ if (!_featuresLoaded) return; let features = []; $('#config-features-content input[type="checkbox"]').each(function () { - features.push({ name: $(this).data('feature-name'), value: $(this).prop('checked').toString() }); + features.push({ name: $(this).data('feature-name'), value: $(this).prop('checked') ? 'True' : 'False' }); }); $('#config-features-json').val(JSON.stringify(features)); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Handlers/TenantCreatedEventHandler.cs b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Handlers/TenantCreatedEventHandler.cs index 7f725c1034..ffc1badf55 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Handlers/TenantCreatedEventHandler.cs +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Application/Handlers/TenantCreatedEventHandler.cs @@ -72,7 +72,7 @@ internal static List BuildFeatureUpdates(string? featureKeysRa return featureKeysRaw .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Select(key => new UpdateFeatureDto { Name = key, Value = "true" }) + .Select(key => new UpdateFeatureDto { Name = key, Value = "True" }) .ToList(); } } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js index e7e05eb9e1..7e4992918b 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/ApplicationForms/Mapping.js @@ -53,26 +53,26 @@ 'bcaddress', 'datagrid']); - const UIElements = { - btnBack: $('#btn-back'), - btnSave: $('#btn-save'), - btnEdit: $('#btn-edit'), - btnGenerate: $('#btn-generate'), - btnGenerateWorksheet: $('#btn-generate-worksheet'), - btnGenerateScoresheet: $('#btn-generate-scoresheet'), - btnReviewWorksheet: $('#btn-review-worksheet'), - worksheetReviewModal: $('#aiWorksheetReviewModal'), - worksheetReviewFields: $('#aiWorksheetReviewFields'), - worksheetReviewEmpty: $('#aiWorksheetReviewEmpty'), - worksheetTitle: $('#aiWorksheetTitle'), - btnCreateWorksheetDraft: $('#btn-create-ai-worksheet-draft'), - btnDiscardWorksheet: $('#btn-discard-ai-worksheet'), - btnSync: $('#btn-sync'), - btnReset: $('#btn-reset'), - btnClose: $('.btn-close'), - btnSaveMapping: $('#btn-save-mapping'), - btnCancel: $('#btn-cancel-mapping'), - inputSearchBar: $('#search-bar'), + const UIElements = { + btnBack: $('#btn-back'), + btnSave: $('#btn-save'), + btnEdit: $('#btn-edit'), + btnGenerate: $('#btn-generate'), + btnGenerateWorksheet: $('#btn-generate-worksheet'), + btnGenerateScoresheet: $('#btn-generate-scoresheet'), + btnReviewWorksheet: $('#btn-review-worksheet'), + worksheetReviewModal: $('#aiWorksheetReviewModal'), + worksheetReviewFields: $('#aiWorksheetReviewFields'), + worksheetReviewEmpty: $('#aiWorksheetReviewEmpty'), + worksheetTitle: $('#aiWorksheetTitle'), + btnCreateWorksheetDraft: $('#btn-create-ai-worksheet-draft'), + btnDiscardWorksheet: $('#btn-discard-ai-worksheet'), + btnSync: $('#btn-sync'), + btnReset: $('#btn-reset'), + btnClose: $('.btn-close'), + btnSaveMapping: $('#btn-save-mapping'), + btnCancel: $('#btn-cancel-mapping'), + inputSearchBar: $('#search-bar'), selectVersionList: $('#applicationFormVersion'), editMappingModal: $('#editMappingModal'), uiConfigurationTab: $('#nav-ui-configuration'), @@ -103,24 +103,24 @@ function bindUIEvents() { UIElements.btnBack.on('click', handleBack); - UIElements.btnSave.on('click', handleSave); - UIElements.btnSaveMapping.on('click', handleSaveEditMapping); - UIElements.btnSync.on('click', handleSync); - UIElements.btnEdit.on('click', handleEdit); - UIElements.btnGenerate.on('click', queueFormMapping); - UIElements.btnGenerateWorksheet.on('click', queueFormWorksheet); - UIElements.btnGenerateScoresheet.on('click', queueFormScoresheet); - UIElements.btnReviewWorksheet.on('click', loadAiWorksheetReview); - UIElements.btnCreateWorksheetDraft.on('click', createAiWorksheetDraft); - UIElements.btnDiscardWorksheet.on('click', discardAiWorksheetSuggestions); - UIElements.worksheetReviewFields.on('change', 'input[data-field-id]', updateAiWorksheetReview); - $('#aiWorksheetReviewSelectAll').on('change', toggleAiWorksheetReviewAll); - UIElements.worksheetTitle.on('input', updateAiWorksheetDraftButton); - UIElements.btnReset.on('click', handleReset); - UIElements.btnCancel.on('click', handleCancelMapping); - UIElements.btnClose.on('click', handleCancelMapping); - UIElements.inputSearchBar.on('keyup', handleSeearchBar); - UIElements.selectVersionList.on('change', handleSelectVersion); + UIElements.btnSave.on('click', handleSave); + UIElements.btnSaveMapping.on('click', handleSaveEditMapping); + UIElements.btnSync.on('click', handleSync); + UIElements.btnEdit.on('click', handleEdit); + UIElements.btnGenerate.on('click', queueFormMapping); + UIElements.btnGenerateWorksheet.on('click', queueFormWorksheet); + UIElements.btnGenerateScoresheet.on('click', queueFormScoresheet); + UIElements.btnReviewWorksheet.on('click', loadAiWorksheetReview); + UIElements.btnCreateWorksheetDraft.on('click', createAiWorksheetDraft); + UIElements.btnDiscardWorksheet.on('click', discardAiWorksheetSuggestions); + UIElements.worksheetReviewFields.on('change', 'input[data-field-id]', updateAiWorksheetReview); + $('#aiWorksheetReviewSelectAll').on('change', toggleAiWorksheetReviewAll); + UIElements.worksheetTitle.on('input', updateAiWorksheetDraftButton); + UIElements.btnReset.on('click', handleReset); + UIElements.btnCancel.on('click', handleCancelMapping); + UIElements.btnClose.on('click', handleCancelMapping); + UIElements.inputSearchBar.on('keyup', handleSeearchBar); + UIElements.selectVersionList.on('change', handleSelectVersion); UIElements.mappingTab.on('click', handleMappingTabClick); // Persist active tab to localStorage on switch @@ -165,487 +165,487 @@ }); } - function handleEdit() { - $('#jsonText').val(prettyJson(existingMappingString)); - UIElements.editMappingModal.addClass('display-modal'); - } - - function queueFormMapping(triggerButton = null) { - const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); - const applicationId = String(document.getElementById('applicationFormId')?.value ?? '').trim(); - if (!validateGuid(formVersion)) { - abp.notify.error('', 'The Form Version ID is not in a GUID format'); - return; - } - if (!validateGuid(applicationId)) { - abp.notify.error('', 'The Application ID is not in a GUID format'); - return; - } - - const buttonElement = triggerButton?.currentTarget || triggerButton?.target || triggerButton || UIElements.btnGenerate?.get?.(0); - const $button = $(buttonElement); - const existingHtml = $button.html(); - - if ($button.prop('disabled')) { - return; - } - - globalThis.AIGenerationButtonState?.setGenerating($button); - - abp.ajax({ - url: `/api/app/ai/generation/form-mapping?applicationId=${encodeURIComponent(applicationId)}&applicationFormVersionId=${encodeURIComponent(formVersion)}`, - type: 'POST', - }) - .done(function (generationStatus) { - const request = generationStatus?.generationRequest; - const status = globalThis.AIGenerationButtonState?.resolveStatus(request?.status) ?? ''; - - if (status === 'Completed') { - globalThis.AIGenerationButtonState?.restoreForCooldownCheck($button, existingHtml); - globalThis.AIGenerationButtonState?.applyStatusState(generationStatus); - refreshMappingAfterGeneration(applicationId, formVersion); - return; - } - - monitorFormMappingGeneration(applicationId, $button, existingHtml); - }) - .fail(function (error) { - if (globalThis.AIGenerationButtonState?.handleQueueFailure(error)) { - return; - } - - abp.message.error('Failed to queue AI mapping generation. Please try again.'); - restoreGenerateMappingButton($button, existingHtml); - globalThis.syncAIRateLimitButtons?.(); - }); - } - - function queueFormWorksheet(triggerButton = null) { - const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); - const applicationId = String(document.getElementById('applicationFormId')?.value ?? '').trim(); - if (!validateGuid(formVersion) || !validateGuid(applicationId)) { - abp.notify.error('', 'The Form Version ID or Application ID is not in a GUID format'); - return; - } - - const buttonElement = triggerButton?.currentTarget || triggerButton?.target || triggerButton || UIElements.btnGenerateWorksheet?.get?.(0); - const $button = $(buttonElement); - - if (isAiWorksheetPending()) { - loadAiWorksheetReview(); - return; - } - - const existingHtml = $button.html(); - - if ($button.prop('disabled')) { - return; - } - - globalThis.AIGenerationButtonState?.setGenerating($button); - - abp.ajax({ - url: `/api/app/ai/generation/form-worksheet?applicationId=${encodeURIComponent(applicationId)}&applicationFormVersionId=${encodeURIComponent(formVersion)}`, - type: 'POST', - }) - .done(function (generationStatus) { - const request = generationStatus?.generationRequest; - const status = globalThis.AIGenerationButtonState?.resolveStatus(request?.status) ?? ''; - if (status === 'Completed') { - globalThis.AIGenerationButtonState?.restoreForCooldownCheck($button, existingHtml); - globalThis.AIGenerationButtonState?.applyStatusState(generationStatus); - refreshWorksheetAfterGeneration(); - return; - } - - monitorFormWorksheetGeneration(applicationId, $button, existingHtml); - }) - .fail(function (error) { - if (globalThis.AIGenerationButtonState?.handleQueueFailure(error)) { - return; - } - - abp.message.error('Failed to queue AI worksheet generation. Please try again.'); - restoreGenerateWorksheetButton($button, existingHtml); - globalThis.syncAIRateLimitButtons?.(); - }); - } - - function monitorFormWorksheetGeneration(applicationId, $button, existingHtml) { - globalThis.AIGenerationButtonState?.monitor({ - $button, - originalHtml: existingHtml, - getStatus: () => abp.ajax({ - url: `/api/app/ai/generation/status?applicationId=${encodeURIComponent(applicationId)}&operationType=form-worksheet`, - type: 'GET' - }), - onComplete: function () { - refreshWorksheetAfterGeneration(); - }, - onFailed: function (request) { - abp.message.error(request?.failureReason || 'AI worksheet generation failed.'); - }, - onPollFailed: function () { - abp.message.error('Unable to load AI worksheet generation status. Please try again.'); - } - }); - } - - function queueFormScoresheet(triggerButton = null) { - const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); - const applicationId = String(document.getElementById('applicationFormId')?.value ?? '').trim(); - if (!validateGuid(formVersion) || !validateGuid(applicationId)) { - abp.notify.error('', 'The Form Version ID or Application ID is not in a GUID format'); - return; - } - - const buttonElement = triggerButton?.currentTarget || triggerButton?.target || triggerButton || UIElements.btnGenerateScoresheet?.get?.(0); - const $button = $(buttonElement); - const existingHtml = $button.html(); - - if ($button.prop('disabled')) { - return; - } - - globalThis.AIGenerationButtonState?.setGenerating($button); - - abp.ajax({ - url: `/api/app/ai/generation/form-scoresheet?applicationId=${encodeURIComponent(applicationId)}&applicationFormVersionId=${encodeURIComponent(formVersion)}`, - type: 'POST', - }) - .done(function (generationStatus) { - const request = generationStatus?.generationRequest; - const status = globalThis.AIGenerationButtonState?.resolveStatus(request?.status) ?? ''; - if (status === 'Completed') { - globalThis.AIGenerationButtonState?.restoreForCooldownCheck($button, existingHtml); - globalThis.AIGenerationButtonState?.applyStatusState(generationStatus); - refreshScoresheetAfterGeneration(); - return; - } - - monitorFormScoresheetGeneration(applicationId, $button, existingHtml); - }) - .fail(function (error) { - if (globalThis.AIGenerationButtonState?.handleQueueFailure(error)) { - return; - } - - abp.message.error('Failed to queue AI scoresheet generation. Please try again.'); - restoreGenerateScoresheetButton($button, existingHtml); - globalThis.syncAIRateLimitButtons?.(); - }); - } - - function monitorFormScoresheetGeneration(applicationId, $button, existingHtml) { - globalThis.AIGenerationButtonState?.monitor({ - $button, - originalHtml: existingHtml, - getStatus: () => abp.ajax({ - url: `/api/app/ai/generation/status?applicationId=${encodeURIComponent(applicationId)}&operationType=form-scoresheet`, - type: 'GET' - }), - onComplete: function () { - refreshScoresheetAfterGeneration(); - }, - onFailed: function (request) { - abp.message.error(request?.failureReason || 'AI scoresheet generation failed.'); - }, - onPollFailed: function () { - abp.message.error('Unable to load AI scoresheet generation status. Please try again.'); - } - }); - } - - function refreshWorksheetAfterGeneration() { - setAiWorksheetPending(true); - abp.notify.success('', 'Worksheet generated. Review the suggested fields and create draft worksheets.'); - loadAiWorksheetReview(); - } - - function isAiWorksheetPending() { - return UIElements.btnGenerateWorksheet.attr('data-ai-pending') === 'true'; - } - - function setAiWorksheetPending(isPending) { - UIElements.btnGenerateWorksheet - .attr('data-ai-pending', isPending ? 'true' : 'false') - .toggleClass('d-none', isPending); - UIElements.btnReviewWorksheet.toggleClass('d-none', !isPending); - - if (!isPending) { - globalThis.syncAIRateLimitButtons?.(); - } - } - - function loadAiWorksheetReview() { - const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); - if (!validateGuid(formVersion)) { - abp.notify.error('', 'Unable to review the worksheet because the Form Version ID is invalid.'); - return; - } - - abp.ajax({ - url: `/api/app/application-form-version/pending-ai-worksheet?formVersionId=${encodeURIComponent(formVersion)}`, - type: 'GET' - }) - .done(function (worksheet) { - if (!worksheet) { - setAiWorksheetPending(false); - abp.notify.error('', 'The pending AI worksheet is no longer available.'); - return; - } - - renderAiWorksheetReview(worksheet); - UIElements.worksheetReviewModal.modal('show'); - }) - .fail(function () { - abp.notify.error('', 'Unable to load the pending AI worksheet.'); - }); - } - - function renderAiWorksheetReview(worksheet) { - UIElements.worksheetReviewFields.empty(); - - const fields = worksheet.fields || []; - fields.forEach(function (field) { - const fieldId = `ai-worksheet-field-${field.id}`; - const $row = $('
'); - $('') - .attr('data-field-role', 'Source') - .text(field.key || '—') - .appendTo($row); - $('').appendTo($row); - $('') - .attr('data-field-role', 'Worksheet') - .text(field.label || field.key || '—') - .appendTo($row); - const $switch = $('
'); - const $switchContainer = $('
'); - $('') - .attr('id', fieldId) - .attr('data-field-id', field.id) - .attr('aria-label', `Include ${field.label || field.key || 'field'}`) - .prop('checked', field.selected !== false) - .appendTo($switchContainer); - $switchContainer.appendTo($switch); - $switch.appendTo($row); - $row.appendTo(UIElements.worksheetReviewFields); - }); - - UIElements.worksheetReviewFields.attr('data-session-id', worksheet.sessionId); - UIElements.worksheetReviewEmpty.toggleClass('d-none', fields.length > 0); - updateAiWorksheetReview(); - } - - function updateAiWorksheetReview() { - const $fields = UIElements.worksheetReviewFields.find('input[data-field-id]'); - const selectedCount = $fields.filter(':checked').length; - $('#aiWorksheetReviewSelectAll') - .prop('checked', $fields.length > 0 && selectedCount === $fields.length) - .prop('indeterminate', false); - updateAiWorksheetDraftButton(); - } - - function toggleAiWorksheetReviewAll() { - UIElements.worksheetReviewFields.find('input[data-field-id]').prop('checked', $(this).prop('checked')); - updateAiWorksheetReview(); - } - - function updateAiWorksheetDraftButton() { - const hasTitle = String(UIElements.worksheetTitle.val() ?? '').trim().length > 0; - const hasSelectedFields = UIElements.worksheetReviewFields.find('input[data-field-id]:checked').length > 0; - UIElements.btnCreateWorksheetDraft.prop('disabled', !hasTitle || !hasSelectedFields); - } - - function createAiWorksheetDraft() { - const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); - const sessionId = UIElements.worksheetReviewFields.attr('data-session-id'); - const title = String(UIElements.worksheetTitle.val() ?? '').trim(); - const selectedFieldIds = UIElements.worksheetReviewFields - .find('input[data-field-id]:checked') - .map(function () { return $(this).attr('data-field-id'); }) - .get(); - - if (!validateGuid(formVersion) || !validateGuid(sessionId) || !title || selectedFieldIds.length === 0) { - abp.notify.error('', 'Enter a worksheet title and select at least one suggested field.'); - return; - } - - UIElements.btnCreateWorksheetDraft.prop('disabled', true); - UIElements.btnDiscardWorksheet.prop('disabled', true); - - abp.ajax({ - url: `/api/app/application-form-version/create-ai-worksheet-draft?formVersionId=${encodeURIComponent(formVersion)}`, - type: 'POST', - contentType: 'application/json', - data: JSON.stringify({ sessionId, title, selectedFieldIds }) - }) - .done(function () { - UIElements.worksheetTitle.val(''); - abp.notify.success('', 'Draft worksheet created.'); - refreshAiWorksheetReviewAfterDraftCreation(formVersion); - }) - .fail(function () { - abp.notify.error('', 'Unable to create the draft worksheet.'); - }) - .always(function () { - UIElements.btnDiscardWorksheet.prop('disabled', false); - updateAiWorksheetDraftButton(); - }); - } - - function refreshAiWorksheetReviewAfterDraftCreation(formVersion) { - abp.ajax({ - url: `/api/app/application-form-version/pending-ai-worksheet?formVersionId=${encodeURIComponent(formVersion)}`, - type: 'GET' - }) - .done(function (worksheet) { - if (!worksheet) { - UIElements.worksheetReviewModal.modal('hide'); - setAiWorksheetPending(false); - return; - } - - renderAiWorksheetReview(worksheet); - }) - .fail(function () { - abp.notify.error('', 'Draft created, but the remaining suggestions could not be loaded.'); - }); - } - - function discardAiWorksheetSuggestions() { - const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); - if (!validateGuid(formVersion) || !isAiWorksheetPending()) { - return; - } - - abp.message.confirm( - 'This will permanently remove the remaining AI field suggestions.', - 'Discard remaining suggestions?') - .then(function (confirmed) { - if (!confirmed) { - return; - } - - UIElements.btnCreateWorksheetDraft.prop('disabled', true); - UIElements.btnDiscardWorksheet.prop('disabled', true); - abp.ajax({ - url: `/api/app/application-form-version/discard-ai-worksheet-suggestions?formVersionId=${encodeURIComponent(formVersion)}`, - type: 'POST' - }) - .done(function () { - setAiWorksheetPending(false); - UIElements.worksheetReviewModal.modal('hide'); - abp.notify.success('', 'Remaining AI worksheet suggestions discarded.'); - }) - .fail(function () { - abp.notify.error('', 'Unable to discard the remaining AI worksheet suggestions.'); - }) - .always(function () { - UIElements.btnDiscardWorksheet.prop('disabled', false); - updateAiWorksheetDraftButton(); - }); - }); - } - - function refreshScoresheetAfterGeneration() { - abp.notify.success('', 'Scoresheet generated and assigned successfully. Reloading page.'); - setTimeout(function () { - globalThis.location.reload(); - }, 500); - } - - function monitorFormMappingGeneration(applicationId, $button, existingHtml) { - globalThis.AIGenerationButtonState?.monitor({ - $button, - originalHtml: existingHtml, - getStatus: () => abp.ajax({ - url: `/api/app/ai/generation/status?applicationId=${encodeURIComponent(applicationId)}&operationType=form-mapping`, - type: 'GET' - }), - onComplete: function () { - refreshMappingAfterGeneration(applicationId); - }, - onFailed: function (request) { - abp.message.error(request?.failureReason || 'AI mapping generation failed.'); - }, - onPollFailed: function () { - abp.message.error('Unable to load AI mapping generation status. Please try again.'); - } - }); - } - - function refreshMappingAfterGeneration(applicationId, formVersion = null) { - const resolvedFormVersion = String(formVersion ?? document.getElementById('formVersionId')?.value ?? '').trim(); - if (!validateGuid(resolvedFormVersion)) { - abp.notify.error('', 'Unable to refresh the generated mapping because the Form Version ID is invalid.'); - return; - } - - abp.ajax({ - url: `/api/app/application-form-version/${encodeURIComponent(resolvedFormVersion)}`, - type: 'GET' - }) - .done(function (applicationFormVersionDto) { - const availableChefsFields = applicationFormVersionDto?.availableChefsFields - ? JSON.parse(applicationFormVersionDto.availableChefsFields) - : []; - - $('#applicationFormVersionDtoString').val(JSON.stringify(applicationFormVersionDto ?? {})); - $('#availableChefsFields').val(applicationFormVersionDto?.availableChefsFields ?? ''); - $('#existingMapping').val(applicationFormVersionDto?.submissionHeaderMapping ?? ''); - - existingMappingString = applicationFormVersionDto?.submissionHeaderMapping ?? ''; - availableChefFieldsString = applicationFormVersionDto?.availableChefsFields ?? ''; - - $(intakeMapColumn).empty(); - $(worksheetMapColumn).empty(); - dataTable.clear().draw(); - initializeIntakeMap(availableChefsFields); - bindExistingMaps(); - - abp.notify.success('', 'Form mapping generated and saved successfully.'); - }) - .fail(function () { - abp.notify.error('', 'Form mapping generated, but the page could not refresh the saved mapping.'); - }); - } - - function restoreGenerateMappingButton($button, existingHtml) { - if (!$button?.length) { - return; - } - - globalThis.AIGenerationButtonState?.restore($button); - $button.html(existingHtml).prop('disabled', false); - $button.find('span').last().text('Generate Mapping'); - } - - function restoreGenerateWorksheetButton($button, existingHtml) { - if (!$button?.length) { - return; - } - - globalThis.AIGenerationButtonState?.restore($button); - $button.html(existingHtml).prop('disabled', false); - $button.find('span').last().text(isAiWorksheetPending() ? 'Review Worksheet' : 'Generate Worksheet'); - } - - function restoreGenerateScoresheetButton($button, existingHtml) { - if (!$button?.length) { - return; - } - - globalThis.AIGenerationButtonState?.restore($button); - $button.html(existingHtml).prop('disabled', false); - $button.find('span').last().text('Generate Scoresheet'); - } - - function handleSaveEditMapping() { - try { - let jsonText = $('#jsonText').val(); - $.parseJSON(jsonText); - let mappingJsonStr = jsonText.replace(/\s+/g, ' ').replace(/(\r\n|\n|\r)/gm, ""); + function handleEdit() { + $('#jsonText').val(prettyJson(existingMappingString)); + UIElements.editMappingModal.addClass('display-modal'); + } + + function queueFormMapping(triggerButton = null) { + const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); + const applicationId = String(document.getElementById('applicationFormId')?.value ?? '').trim(); + if (!validateGuid(formVersion)) { + abp.notify.error('', 'The Form Version ID is not in a GUID format'); + return; + } + if (!validateGuid(applicationId)) { + abp.notify.error('', 'The Application ID is not in a GUID format'); + return; + } + + const buttonElement = triggerButton?.currentTarget || triggerButton?.target || triggerButton || UIElements.btnGenerate?.get?.(0); + const $button = $(buttonElement); + const existingHtml = $button.html(); + + if ($button.prop('disabled')) { + return; + } + + globalThis.AIGenerationButtonState?.setGenerating($button); + + abp.ajax({ + url: `/api/app/ai/generation/form-mapping?applicationId=${encodeURIComponent(applicationId)}&applicationFormVersionId=${encodeURIComponent(formVersion)}`, + type: 'POST', + }) + .done(function (generationStatus) { + const request = generationStatus?.generationRequest; + const status = globalThis.AIGenerationButtonState?.resolveStatus(request?.status) ?? ''; + + if (status === 'Completed') { + globalThis.AIGenerationButtonState?.restoreForCooldownCheck($button, existingHtml); + globalThis.AIGenerationButtonState?.applyStatusState(generationStatus); + refreshMappingAfterGeneration(applicationId, formVersion); + return; + } + + monitorFormMappingGeneration(applicationId, $button, existingHtml); + }) + .fail(function (error) { + if (globalThis.AIGenerationButtonState?.handleQueueFailure(error)) { + return; + } + + abp.message.error('Failed to queue AI mapping generation. Please try again.'); + restoreGenerateMappingButton($button, existingHtml); + globalThis.syncAIRateLimitButtons?.(); + }); + } + + function queueFormWorksheet(triggerButton = null) { + const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); + const applicationId = String(document.getElementById('applicationFormId')?.value ?? '').trim(); + if (!validateGuid(formVersion) || !validateGuid(applicationId)) { + abp.notify.error('', 'The Form Version ID or Application ID is not in a GUID format'); + return; + } + + const buttonElement = triggerButton?.currentTarget || triggerButton?.target || triggerButton || UIElements.btnGenerateWorksheet?.get?.(0); + const $button = $(buttonElement); + + if (isAiWorksheetPending()) { + loadAiWorksheetReview(); + return; + } + + const existingHtml = $button.html(); + + if ($button.prop('disabled')) { + return; + } + + globalThis.AIGenerationButtonState?.setGenerating($button); + + abp.ajax({ + url: `/api/app/ai/generation/form-worksheet?applicationId=${encodeURIComponent(applicationId)}&applicationFormVersionId=${encodeURIComponent(formVersion)}`, + type: 'POST', + }) + .done(function (generationStatus) { + const request = generationStatus?.generationRequest; + const status = globalThis.AIGenerationButtonState?.resolveStatus(request?.status) ?? ''; + if (status === 'Completed') { + globalThis.AIGenerationButtonState?.restoreForCooldownCheck($button, existingHtml); + globalThis.AIGenerationButtonState?.applyStatusState(generationStatus); + refreshWorksheetAfterGeneration(); + return; + } + + monitorFormWorksheetGeneration(applicationId, $button, existingHtml); + }) + .fail(function (error) { + if (globalThis.AIGenerationButtonState?.handleQueueFailure(error)) { + return; + } + + abp.message.error('Failed to queue AI worksheet generation. Please try again.'); + restoreGenerateWorksheetButton($button, existingHtml); + globalThis.syncAIRateLimitButtons?.(); + }); + } + + function monitorFormWorksheetGeneration(applicationId, $button, existingHtml) { + globalThis.AIGenerationButtonState?.monitor({ + $button, + originalHtml: existingHtml, + getStatus: () => abp.ajax({ + url: `/api/app/ai/generation/status?applicationId=${encodeURIComponent(applicationId)}&operationType=form-worksheet`, + type: 'GET' + }), + onComplete: function () { + refreshWorksheetAfterGeneration(); + }, + onFailed: function (request) { + abp.message.error(request?.failureReason || 'AI worksheet generation failed.'); + }, + onPollFailed: function () { + abp.message.error('Unable to load AI worksheet generation status. Please try again.'); + } + }); + } + + function queueFormScoresheet(triggerButton = null) { + const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); + const applicationId = String(document.getElementById('applicationFormId')?.value ?? '').trim(); + if (!validateGuid(formVersion) || !validateGuid(applicationId)) { + abp.notify.error('', 'The Form Version ID or Application ID is not in a GUID format'); + return; + } + + const buttonElement = triggerButton?.currentTarget || triggerButton?.target || triggerButton || UIElements.btnGenerateScoresheet?.get?.(0); + const $button = $(buttonElement); + const existingHtml = $button.html(); + + if ($button.prop('disabled')) { + return; + } + + globalThis.AIGenerationButtonState?.setGenerating($button); + + abp.ajax({ + url: `/api/app/ai/generation/form-scoresheet?applicationId=${encodeURIComponent(applicationId)}&applicationFormVersionId=${encodeURIComponent(formVersion)}`, + type: 'POST', + }) + .done(function (generationStatus) { + const request = generationStatus?.generationRequest; + const status = globalThis.AIGenerationButtonState?.resolveStatus(request?.status) ?? ''; + if (status === 'Completed') { + globalThis.AIGenerationButtonState?.restoreForCooldownCheck($button, existingHtml); + globalThis.AIGenerationButtonState?.applyStatusState(generationStatus); + refreshScoresheetAfterGeneration(); + return; + } + + monitorFormScoresheetGeneration(applicationId, $button, existingHtml); + }) + .fail(function (error) { + if (globalThis.AIGenerationButtonState?.handleQueueFailure(error)) { + return; + } + + abp.message.error('Failed to queue AI scoresheet generation. Please try again.'); + restoreGenerateScoresheetButton($button, existingHtml); + globalThis.syncAIRateLimitButtons?.(); + }); + } + + function monitorFormScoresheetGeneration(applicationId, $button, existingHtml) { + globalThis.AIGenerationButtonState?.monitor({ + $button, + originalHtml: existingHtml, + getStatus: () => abp.ajax({ + url: `/api/app/ai/generation/status?applicationId=${encodeURIComponent(applicationId)}&operationType=form-scoresheet`, + type: 'GET' + }), + onComplete: function () { + refreshScoresheetAfterGeneration(); + }, + onFailed: function (request) { + abp.message.error(request?.failureReason || 'AI scoresheet generation failed.'); + }, + onPollFailed: function () { + abp.message.error('Unable to load AI scoresheet generation status. Please try again.'); + } + }); + } + + function refreshWorksheetAfterGeneration() { + setAiWorksheetPending(true); + abp.notify.success('', 'Worksheet generated. Review the suggested fields and create draft worksheets.'); + loadAiWorksheetReview(); + } + + function isAiWorksheetPending() { + return UIElements.btnGenerateWorksheet.attr('data-ai-pending') === 'true'; + } + + function setAiWorksheetPending(isPending) { + UIElements.btnGenerateWorksheet + .attr('data-ai-pending', isPending ? 'true' : 'false') + .toggleClass('d-none', isPending); + UIElements.btnReviewWorksheet.toggleClass('d-none', !isPending); + + if (!isPending) { + globalThis.syncAIRateLimitButtons?.(); + } + } + + function loadAiWorksheetReview() { + const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); + if (!validateGuid(formVersion)) { + abp.notify.error('', 'Unable to review the worksheet because the Form Version ID is invalid.'); + return; + } + + abp.ajax({ + url: `/api/app/application-form-version/pending-ai-worksheet?formVersionId=${encodeURIComponent(formVersion)}`, + type: 'GET' + }) + .done(function (worksheet) { + if (!worksheet) { + setAiWorksheetPending(false); + abp.notify.error('', 'The pending AI worksheet is no longer available.'); + return; + } + + renderAiWorksheetReview(worksheet); + UIElements.worksheetReviewModal.modal('show'); + }) + .fail(function () { + abp.notify.error('', 'Unable to load the pending AI worksheet.'); + }); + } + + function renderAiWorksheetReview(worksheet) { + UIElements.worksheetReviewFields.empty(); + + const fields = worksheet.fields || []; + fields.forEach(function (field) { + const fieldId = `ai-worksheet-field-${field.id}`; + const $row = $('
'); + $('') + .attr('data-field-role', 'Source') + .text(field.key || '—') + .appendTo($row); + $('').appendTo($row); + $('') + .attr('data-field-role', 'Worksheet') + .text(field.label || field.key || '—') + .appendTo($row); + const $switch = $('
'); + const $switchContainer = $('
'); + $('') + .attr('id', fieldId) + .attr('data-field-id', field.id) + .attr('aria-label', `Include ${field.label || field.key || 'field'}`) + .prop('checked', field.selected !== false) + .appendTo($switchContainer); + $switchContainer.appendTo($switch); + $switch.appendTo($row); + $row.appendTo(UIElements.worksheetReviewFields); + }); + + UIElements.worksheetReviewFields.attr('data-session-id', worksheet.sessionId); + UIElements.worksheetReviewEmpty.toggleClass('d-none', fields.length > 0); + updateAiWorksheetReview(); + } + + function updateAiWorksheetReview() { + const $fields = UIElements.worksheetReviewFields.find('input[data-field-id]'); + const selectedCount = $fields.filter(':checked').length; + $('#aiWorksheetReviewSelectAll') + .prop('checked', $fields.length > 0 && selectedCount === $fields.length) + .prop('indeterminate', false); + updateAiWorksheetDraftButton(); + } + + function toggleAiWorksheetReviewAll() { + UIElements.worksheetReviewFields.find('input[data-field-id]').prop('checked', $(this).prop('checked')); + updateAiWorksheetReview(); + } + + function updateAiWorksheetDraftButton() { + const hasTitle = String(UIElements.worksheetTitle.val() ?? '').trim().length > 0; + const hasSelectedFields = UIElements.worksheetReviewFields.find('input[data-field-id]:checked').length > 0; + UIElements.btnCreateWorksheetDraft.prop('disabled', !hasTitle || !hasSelectedFields); + } + + function createAiWorksheetDraft() { + const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); + const sessionId = UIElements.worksheetReviewFields.attr('data-session-id'); + const title = String(UIElements.worksheetTitle.val() ?? '').trim(); + const selectedFieldIds = UIElements.worksheetReviewFields + .find('input[data-field-id]:checked') + .map(function () { return $(this).attr('data-field-id'); }) + .get(); + + if (!validateGuid(formVersion) || !validateGuid(sessionId) || !title || selectedFieldIds.length === 0) { + abp.notify.error('', 'Enter a worksheet title and select at least one suggested field.'); + return; + } + + UIElements.btnCreateWorksheetDraft.prop('disabled', true); + UIElements.btnDiscardWorksheet.prop('disabled', true); + + abp.ajax({ + url: `/api/app/application-form-version/create-ai-worksheet-draft?formVersionId=${encodeURIComponent(formVersion)}`, + type: 'POST', + contentType: 'application/json', + data: JSON.stringify({ sessionId, title, selectedFieldIds }) + }) + .done(function () { + UIElements.worksheetTitle.val(''); + abp.notify.success('', 'Draft worksheet created.'); + refreshAiWorksheetReviewAfterDraftCreation(formVersion); + }) + .fail(function () { + abp.notify.error('', 'Unable to create the draft worksheet.'); + }) + .always(function () { + UIElements.btnDiscardWorksheet.prop('disabled', false); + updateAiWorksheetDraftButton(); + }); + } + + function refreshAiWorksheetReviewAfterDraftCreation(formVersion) { + abp.ajax({ + url: `/api/app/application-form-version/pending-ai-worksheet?formVersionId=${encodeURIComponent(formVersion)}`, + type: 'GET' + }) + .done(function (worksheet) { + if (!worksheet) { + UIElements.worksheetReviewModal.modal('hide'); + setAiWorksheetPending(false); + return; + } + + renderAiWorksheetReview(worksheet); + }) + .fail(function () { + abp.notify.error('', 'Draft created, but the remaining suggestions could not be loaded.'); + }); + } + + function discardAiWorksheetSuggestions() { + const formVersion = String(document.getElementById('formVersionId')?.value ?? '').trim(); + if (!validateGuid(formVersion) || !isAiWorksheetPending()) { + return; + } + + abp.message.confirm( + 'This will permanently remove the remaining AI field suggestions.', + 'Discard remaining suggestions?') + .then(function (confirmed) { + if (!confirmed) { + return; + } + + UIElements.btnCreateWorksheetDraft.prop('disabled', true); + UIElements.btnDiscardWorksheet.prop('disabled', true); + abp.ajax({ + url: `/api/app/application-form-version/discard-ai-worksheet-suggestions?formVersionId=${encodeURIComponent(formVersion)}`, + type: 'POST' + }) + .done(function () { + setAiWorksheetPending(false); + UIElements.worksheetReviewModal.modal('hide'); + abp.notify.success('', 'Remaining AI worksheet suggestions discarded.'); + }) + .fail(function () { + abp.notify.error('', 'Unable to discard the remaining AI worksheet suggestions.'); + }) + .always(function () { + UIElements.btnDiscardWorksheet.prop('disabled', false); + updateAiWorksheetDraftButton(); + }); + }); + } + + function refreshScoresheetAfterGeneration() { + abp.notify.success('', 'Scoresheet generated and assigned successfully. Reloading page.'); + setTimeout(function () { + globalThis.location.reload(); + }, 500); + } + + function monitorFormMappingGeneration(applicationId, $button, existingHtml) { + globalThis.AIGenerationButtonState?.monitor({ + $button, + originalHtml: existingHtml, + getStatus: () => abp.ajax({ + url: `/api/app/ai/generation/status?applicationId=${encodeURIComponent(applicationId)}&operationType=form-mapping`, + type: 'GET' + }), + onComplete: function () { + refreshMappingAfterGeneration(applicationId); + }, + onFailed: function (request) { + abp.message.error(request?.failureReason || 'AI mapping generation failed.'); + }, + onPollFailed: function () { + abp.message.error('Unable to load AI mapping generation status. Please try again.'); + } + }); + } + + function refreshMappingAfterGeneration(applicationId, formVersion = null) { + const resolvedFormVersion = String(formVersion ?? document.getElementById('formVersionId')?.value ?? '').trim(); + if (!validateGuid(resolvedFormVersion)) { + abp.notify.error('', 'Unable to refresh the generated mapping because the Form Version ID is invalid.'); + return; + } + + abp.ajax({ + url: `/api/app/application-form-version/${encodeURIComponent(resolvedFormVersion)}`, + type: 'GET' + }) + .done(function (applicationFormVersionDto) { + const availableChefsFields = applicationFormVersionDto?.availableChefsFields + ? JSON.parse(applicationFormVersionDto.availableChefsFields) + : []; + + $('#applicationFormVersionDtoString').val(JSON.stringify(applicationFormVersionDto ?? {})); + $('#availableChefsFields').val(applicationFormVersionDto?.availableChefsFields ?? ''); + $('#existingMapping').val(applicationFormVersionDto?.submissionHeaderMapping ?? ''); + + existingMappingString = applicationFormVersionDto?.submissionHeaderMapping ?? ''; + availableChefFieldsString = applicationFormVersionDto?.availableChefsFields ?? ''; + + $(intakeMapColumn).empty(); + $(worksheetMapColumn).empty(); + dataTable.clear().draw(); + initializeIntakeMap(availableChefsFields); + bindExistingMaps(); + + abp.notify.success('', 'Form mapping generated and saved successfully.'); + }) + .fail(function () { + abp.notify.error('', 'Form mapping generated, but the page could not refresh the saved mapping.'); + }); + } + + function restoreGenerateMappingButton($button, existingHtml) { + if (!$button?.length) { + return; + } + + globalThis.AIGenerationButtonState?.restore($button); + $button.html(existingHtml).prop('disabled', false); + $button.find('span').last().text('Generate Mapping'); + } + + function restoreGenerateWorksheetButton($button, existingHtml) { + if (!$button?.length) { + return; + } + + globalThis.AIGenerationButtonState?.restore($button); + $button.html(existingHtml).prop('disabled', false); + $button.find('span').last().text(isAiWorksheetPending() ? 'Review Worksheet' : 'Generate Worksheet'); + } + + function restoreGenerateScoresheetButton($button, existingHtml) { + if (!$button?.length) { + return; + } + + globalThis.AIGenerationButtonState?.restore($button); + $button.html(existingHtml).prop('disabled', false); + $button.find('span').last().text('Generate Scoresheet'); + } + + function handleSaveEditMapping() { + try { + let jsonText = $('#jsonText').val(); + $.parseJSON(jsonText); + let mappingJsonStr = jsonText.replaceAll(/\s+/g, ' ').replaceAll(/(\r\n|\n|\r)/gm, ""); UIElements.btnSaveMapping.prop('disabled', true); handleSaveMapping($.parseJSON(mappingJsonStr)); handleCancelMapping(); @@ -666,12 +666,12 @@ '', 'The JSON is not valid:' + err ); - } - } - - function handleCancelMapping() { - UIElements.editMappingModal.removeClass('display-modal'); - } + } + } + + function handleCancelMapping() { + UIElements.editMappingModal.removeClass('display-modal'); + } function handleSeearchBar(e) { let filterValue = e.currentTarget.value; @@ -1067,4 +1067,4 @@ function dragEnd(ev) { if (draggedEl.classList + "" !== "undefined") { draggedEl.classList.remove('dragging'); } -} +} diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.js index 472427545d..64730ae904 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Pages/BulkApprovals/ApproveApplicationsModal.js @@ -7,11 +7,11 @@ function approvedAmountUpdated(event) { const input = event.target; - const value = Number.parseFloat(input.value.replace(/,/g, '')); + const value = Number.parseFloat(input.value.replaceAll(',', '')); setNote(event.target, '_APPROVED_AMOUNT_DEFAULTED', false); - if (isNaN(value) || value <= 0) { + if (Number.isNaN(value) || value <= 0) { setNote(event.target, '_INVALID_APPROVED_AMOUNT', true); } else { setNote(event.target, '_INVALID_APPROVED_AMOUNT', false); @@ -45,11 +45,11 @@ function runValidations() { $('#bulkApprovalForm input[name="BulkApplicationApprovals.Index"]').each(function () { itemCount++; let index = $(this).val(); - let approvedAmount = Number.parseFloat($('#bulkApprovalForm input[name="BulkApplicationApprovals[' + index + '].ApprovedAmount"]').val().replace(/,/g, '')); + let approvedAmount = Number.parseFloat($('#bulkApprovalForm input[name="BulkApplicationApprovals[' + index + '].ApprovedAmount"]').val().replaceAll(',', '')); let decisionDate = new Date($('#bulkApprovalForm input[name="BulkApplicationApprovals[' + index + '].DecisionDate"]').val()); let isValidField = $('#bulkApprovalForm input[name="BulkApplicationApprovals[' + index + '].IsValid"]').val(); - if (isValidField.toLowerCase() !== 'true' || isNaN(approvedAmount) || approvedAmount <= 0 || isNaN(decisionDate.getTime()) || decisionDate > new Date()) { + if (isValidField.toLowerCase() !== 'true' || Number.isNaN(approvedAmount) || approvedAmount <= 0 || Number.isNaN(decisionDate.getTime()) || decisionDate > new Date()) { isValid = false; } }); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js index 32e1d0cf6d..59eef6c365 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantInfo/Default.js @@ -203,7 +203,7 @@ abp.widgets.ApplicantInfo = function ($wrapper) { let fieldValue = input.value; if (inputElement.hasClass('unity-currency-input') || inputElement.hasClass('numeric-mask')) { - fieldValue = fieldValue.replace(/,/g, ''); + fieldValue = fieldValue.replaceAll(',', ''); } if (fieldName.startsWith('ApplicantInfo.')) { diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js index 1ef07dd83e..a9ce274fc8 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ApplicantOrganizationInfo/Default.js @@ -129,7 +129,7 @@ if (typeof value === 'string') { if ($input.hasClass('unity-currency-input') || $input.hasClass('numeric-mask')) { - value = value.replace(/,/g, ''); + value = value.replaceAll(',', ''); } const trimmed = value.trim(); diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js index d42cf25888..b7692db837 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/AssessmentResults/Default.js @@ -20,7 +20,7 @@ let inputElement = $('[name="' + input.name + '"]'); // This will not work if the culture is different and uses a different decimal separator if (inputElement.hasClass('unity-currency-input')) { - assessmentResultObj[input.name.split(".")[1]] = input.value.replace(/,/g, ''); + assessmentResultObj[input.name.split(".")[1]] = input.value.replaceAll(',', ''); } else { assessmentResultObj[input.name.split(".")[1]] = input.value; diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js index 1917dabff4..56db3501e0 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/EmailsWidget/Default.js @@ -2807,7 +2807,7 @@ function isValidDate(month, day, year) { * @returns {string} Title-cased string */ function toTitleCase(str) { - return str.toLowerCase().replace(/\b\w/g, function (char) { + return str.toLowerCase().replaceAll(/\b\w/g, function (char) { return char.toUpperCase(); }); } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js index 8915d95593..154fba37e1 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/ProjectInfo/Default.js @@ -222,9 +222,9 @@ abp.widgets.ProjectInfo = function ($wrapper) { const propertyName = fieldName.split('.')[1]; if (inputElement.hasClass('unity-currency-input') || inputElement.hasClass('numeric-mask')) { - fieldValue = fieldValue.replace(/,/g, ''); + fieldValue = fieldValue.replaceAll(',', ''); } - + if (this.isNumberField(input)) { fieldValue = fieldValue === '' ? 0 : Math.min(Number.parseFloat(fieldValue), this.getMaxNumberField(input)); } else if (fieldValue === '') { @@ -298,9 +298,9 @@ $(function () { }); function calculatePercentage() { - const requestedAmount = Number.parseFloat(document.getElementById("RequestedAmountInputPI")?.value.replace(/,/g, '')); - const totalProjectBudget = Number.parseFloat(document.getElementById("TotalBudgetInputPI")?.value.replace(/,/g, '')); - if (isNaN(requestedAmount) || isNaN(totalProjectBudget) || totalProjectBudget == 0) { + const requestedAmount = Number.parseFloat(document.getElementById("RequestedAmountInputPI")?.value.replaceAll(',', '')); + const totalProjectBudget = Number.parseFloat(document.getElementById("TotalBudgetInputPI")?.value.replaceAll(',', '')); + if (Number.isNaN(requestedAmount) || Number.isNaN(totalProjectBudget) || totalProjectBudget == 0) { document.getElementById("ProjectInfo_PercentageTotalProjectBudget").value = 0; return; } diff --git a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/_Shared/string-utils.js b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/_Shared/string-utils.js index dc7862ccf7..bb9ef5438e 100644 --- a/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/_Shared/string-utils.js +++ b/applications/Unity.GrantManager/src/Unity.GrantManager.Web/Views/Shared/Components/_Shared/string-utils.js @@ -56,7 +56,7 @@ function stripHtml(html) { // Server-side or DOM unavailable: remove HTML tag delimiters directly. // Character-level replacement avoids incomplete multi-character sanitization bypasses. - return String(html).replace(/[<>]/g, ''); + return String(html).replaceAll(/[<>]/g, ''); } /** diff --git a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Handlers/TenantCreatedEventHandlerTests.cs b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Handlers/TenantCreatedEventHandlerTests.cs index 68ad2398d1..c47f6fe57c 100644 --- a/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Handlers/TenantCreatedEventHandlerTests.cs +++ b/applications/Unity.GrantManager/test/Unity.GrantManager.Application.Tests/Handlers/TenantCreatedEventHandlerTests.cs @@ -29,7 +29,7 @@ public void BuildFeatureUpdates_CommaSeparatedKeys_ReturnsOneEnabledUpdatePerKey var result = TenantCreatedEventHandler.BuildFeatureUpdates("Unity.Payments, Unity.Reporting ,Unity.Notifications"); result.Count.ShouldBe(3); - result.ShouldAllBe(f => f.Value == "true"); + result.ShouldAllBe(f => f.Value == "True"); result.ShouldContain(f => f.Name == "Unity.Payments"); result.ShouldContain(f => f.Name == "Unity.Reporting"); result.ShouldContain(f => f.Name == "Unity.Notifications"); diff --git a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/content-script.js b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/content-script.js index 6d428d83ac..f8454cbdd2 100644 --- a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/content-script.js +++ b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/content-script.js @@ -45,15 +45,15 @@ } function cleanText(value) { - return String(value || '').replace(/\s+/g, ' ').trim(); + return String(value || '').replaceAll(/\s+/g, ' ').trim(); } function normalizeRulePhrase(value, caseSensitive) { let normalized = cleanText(String(value || '') - .replace(/<[^>]*>/g, ' ') - .replace(/^[*:\-\s]+|[*:\-\s]+$/g, ' ')) - .replace(/[^A-Za-z0-9]+/g, ' ') - .replace(/\s+/g, ' ') + .replaceAll(/<[^>]*>/g, ' ') + .replaceAll(/^[*:\-\s]+|[*:\-\s]+$/g, ' ')) + .replaceAll(/[^A-Za-z0-9]+/g, ' ') + .replaceAll(/\s+/g, ' ') .trim(); if (!caseSensitive) { normalized = normalized.toLowerCase(); @@ -642,7 +642,7 @@ if (window.CSS && typeof window.CSS.escape === 'function') { return window.CSS.escape(String(value || '')); } - return String(value || '').replace(/[^A-Za-z0-9_-]/g, '\\$&'); + return String(value || '').replaceAll(/[^A-Za-z0-9_-]/g, '\\$&'); } liveWrapper(descriptor) { @@ -1904,9 +1904,9 @@ } maskTokenCharacters(descriptor, attempt) { - const seed = `${this.runId}${descriptor.key}${attempt || 1}`.toUpperCase().replace(/[^A-Z0-9]/g, ''); - const digits = (seed.replace(/[^0-9]/g, '') + '12345678901234567890'); - const letters = (seed.replace(/[^A-Z]/g, '').replace(/[IOQ]/g, '') + 'ABCDEFGHJKLMNPRSTUVWXYZ'); + const seed = `${this.runId}${descriptor.key}${attempt || 1}`.toUpperCase().replaceAll(/[^A-Z0-9]/g, ''); + const digits = (seed.replaceAll(/[^0-9]/g, '') + '12345678901234567890'); + const letters = (seed.replaceAll(/[^A-Z]/g, '').replaceAll(/[IOQ]/g, '') + 'ABCDEFGHJKLMNPRSTUVWXYZ'); const alphaNumeric = `${letters}${digits}`; return { digits, letters, alphaNumeric }; } @@ -1961,7 +1961,7 @@ let escaped = false; for (const character of String(mask || '')) { if (escaped) { - pattern += character.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + pattern += character.replaceAll(/[.*+?^${}()|[\]\\]/g, '\\$&'); escaped = false; } else if (character === '\\') { escaped = true; @@ -1972,7 +1972,7 @@ } else if (character === '*') { pattern += '[A-Za-z0-9]'; } else { - pattern += character.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + pattern += character.replaceAll(/[.*+?^${}()|[\]\\]/g, '\\$&'); } } pattern += '$'; @@ -2168,9 +2168,9 @@ role = 'contact4'; } else { const keySlug = String(descriptor.key || 'contact') - .replace(/([a-z0-9])([A-Z])/g, '$1-$2') - .replace(/[^a-z0-9]+/gi, '-') - .replace(/^-+|-+$/g, '') + .replaceAll(/([a-z0-9])([A-Z])/g, '$1-$2') + .replaceAll(/[^a-z0-9]+/gi, '-') + .replaceAll(/^-+|-+$/g, '') .toLowerCase(); role = keySlug.slice(-32) || 'contact'; } @@ -2363,12 +2363,12 @@ } try { if (input.inputmask && typeof input.inputmask.unmaskedvalue === 'function') { - return String(input.inputmask.unmaskedvalue() || '').replace(/\D/g, '').length; + return String(input.inputmask.unmaskedvalue() || '').replaceAll(/\D/g, '').length; } } catch (error) { // Fall back to the rendered value. } - return String(input.value || '').replace(/\D/g, '').length; + return String(input.value || '').replaceAll(/\D/g, '').length; } async fillPhone(descriptor, attempt) { diff --git a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/options.js b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/options.js index fe4f4d24f2..1e8d9d703c 100644 --- a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/options.js +++ b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/options.js @@ -30,9 +30,9 @@ function newRuleId() { function normalizePhrase(value) { return String(value || '') - .replace(/<[^>]*>/g, ' ') - .replace(/[\u00a0\s]+/g, ' ') - .replace(/^[*:\-\s]+|[*:\-\s]+$/g, '') + .replaceAll(/<[^>]*>/g, ' ') + .replaceAll(/[\u00a0\s]+/g, ' ') + .replaceAll(/^[*:\-\s]+|[*:\-\s]+$/g, '') .trim(); } @@ -340,7 +340,7 @@ async function selectExportFolder() { } function generateBatchToken() { - const token = crypto.randomUUID().replace(/-/g, '') + crypto.randomUUID().replace(/-/g, ''); + const token = crypto.randomUUID().replaceAll('-', '') + crypto.randomUUID().replaceAll('-', ''); document.getElementById('batchLauncherToken').value = token; setBatchSettingsMessage('Token generated. Copy it into LAUNCHER_TOKEN in the batch file, then save Settings.', 'success'); } @@ -413,7 +413,7 @@ function exportRules() { rules: validation.rules }; const data = `data:application/json;charset=utf-8,${encodeURIComponent(JSON.stringify(payload, null, 2))}`; - const stamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\..+/, '').replace('T', '-'); + const stamp = new Date().toISOString().replaceAll(/[-:]/g, '').replace(/\..+/, '').replace('T', '-'); chrome.downloads.download({ url: data, filename: `chefs-custom-format-rules-v${RULE_SCHEMA_VERSION}-${stamp}.json`, diff --git a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/page-bridge.js b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/page-bridge.js index 82cc4d76ab..ce5359e180 100644 --- a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/page-bridge.js +++ b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/page-bridge.js @@ -495,7 +495,7 @@ } const escapedKey = window.CSS && typeof window.CSS.escape === 'function' ? window.CSS.escape(key) - : String(key).replace(/[^A-Za-z0-9_-]/g, '\\$&'); + : String(key).replaceAll(/[^A-Za-z0-9_-]/g, '\\$&'); const wrappers = Array.from(document.querySelectorAll(`.formio-component-${escapedKey}`)); return wrappers.find((item) => renderedWrapperIsVisible(item)) || wrappers.find((item) => item.isConnected) || @@ -512,7 +512,7 @@ '[ref="fileLink"], [ref="fileName"], .file-name, .file-list a, a[download]' )); const matches = candidates.filter((element) => { - const text = String(element.textContent || '').replace(/\s+/g, ' ').trim(); + const text = String(element.textContent || '').replaceAll(/\s+/g, ' ').trim(); const hasRemoveControl = Boolean(element.querySelector && element.querySelector( 'button[ref*="remove"], button[aria-label*="remove" i], .fa-times, .fa-times-circle-o' )); diff --git a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/service-worker.js b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/service-worker.js index 8bd5c3107b..fd700ee391 100644 --- a/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/service-worker.js +++ b/applications/Unity.Tools/Unity.CHEFS/chefs-one-click-form-tester/service-worker.js @@ -706,8 +706,8 @@ function parseBatchMarker(urlText) { url.hash = parameters.toString() ? `#${parameters.toString()}` : ''; return { token, - suiteId: rawSuiteId.replace(/[^A-Za-z0-9_-]/g, '').slice(0, 64) || 'regression', - index: rawIndex.replace(/[^A-Za-z0-9_-]/g, '').slice(0, 32) || '0', + suiteId: rawSuiteId.replaceAll(/[^A-Za-z0-9_-]/g, '').slice(0, 64) || 'regression', + index: rawIndex.replaceAll(/[^A-Za-z0-9_-]/g, '').slice(0, 32) || '0', url: url.href, origin: url.origin }; @@ -1346,8 +1346,8 @@ function createRunBundle(run) { files.push({ name: 'failure-screenshot.png', data: dataUrlToBytes(run.failureScreenshotDataUrl) }); } const zip = createZip(files); - const safeRun = String(run.runId).replace(/[^A-Za-z0-9_-]/g, ''); - const stamp = new Date(run.startedAt || Date.now()).toISOString().replace(/[-:]/g, '').replace(/\..+/, '').replace('T', '-'); + const safeRun = String(run.runId).replaceAll(/[^A-Za-z0-9_-]/g, ''); + const stamp = new Date(run.startedAt || Date.now()).toISOString().replaceAll(/[-:]/g, '').replace(/\..+/, '').replace('T', '-'); const filename = `chefs-one-click-tester-v${run.extensionVersion}-build-${run.buildNumber}-run-${safeRun}-${stamp}.zip`; const url = `data:application/zip;base64,${bytesToBase64(zip)}`; return { filename, url };