Skip to content

Commit

Permalink
TASK 3284: Fix Application json form data generation bugs, release 0.…
Browse files Browse the repository at this point in the history
…9.3 (#61)
  • Loading branch information
mihailistov committed Mar 25, 2024
1 parent 83bf53c commit ae12164
Show file tree
Hide file tree
Showing 11 changed files with 774 additions and 38 deletions.
2 changes: 1 addition & 1 deletion assets/application/js/application.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(function () {
const src =
'https://cdn.jsdelivr.net/gh/bcgov/nr-af-pods@dev/powerpod/releases/powerpod-0.9.2.min.js';
'https://cdn.jsdelivr.net/gh/bcgov/nr-af-pods@dev/powerpod/releases/powerpod-0.9.3.min.js';
const script = document.createElement('script');
script.setAttribute('async', '');
script.src = src;
Expand Down
2 changes: 1 addition & 1 deletion assets/claim/js/claim.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(function () {
const src =
'https://cdn.jsdelivr.net/gh/bcgov/nr-af-pods@dev/powerpod/releases/powerpod-0.9.2.min.js';
'https://cdn.jsdelivr.net/gh/bcgov/nr-af-pods@dev/powerpod/releases/powerpod-0.9.3.min.js';
const script = document.createElement('script');
script.setAttribute('async', '');
script.src = src;
Expand Down
2 changes: 1 addition & 1 deletion powerpod/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "powerpod",
"type": "module",
"version": "0.9.2",
"version": "0.9.3",
"description": "Powerpod is a jQuery plugin that enhances functionality of Power Pages components.",
"main": "dist/powerpod",
"scripts": {
Expand Down
479 changes: 479 additions & 0 deletions powerpod/releases/powerpod-0.9.3.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion powerpod/rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-import-css';

const licenseContent = `/*!
* powerpod 0.9.2
* powerpod 0.9.3
* https://github.com/bcgov/nr-af-pods/powerpod
*
* @license GPLv3 for open source use only
Expand Down
8 changes: 8 additions & 0 deletions powerpod/src/js/application/steps/documents.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,12 @@ export function customizeDocumentsStep() {
// @ts-ignore
$(existingDocumentsHtml).replaceWith(documentsHtml);
}

// TODO: use this for doc step completion TASK 3631
// const entityFormDiv = document.querySelector('#EntityFormView');
// let docUrl =
// 'https://af-pods-dev.powerappsportals.com/claim-documents/?id=d3c11c55-b8d5-ee11-904d-6045bd61cd59';
// let documentsIframeDiv = document.createElement('div');
// documentsIframeDiv.innerHTML = `<iframe id='documentsIframeDiv' src="${docUrl}" height="800" width="100%" title="Documents Uploaded">
// </iframe><br/>`;
}
227 changes: 227 additions & 0 deletions powerpod/src/js/claim/documents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import { Logger } from '../common/logger.js';

const logger = new Logger('claim/documents');

const MAXIMUM_FILE_SIZE_IN_KB = 15360;
const ALLOWED_MIME_TYPES = [
'text/csv',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.oasis.opendocument.text',
'application/pdf',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.oasis.opendocument.spreadsheet',
'image/gif',
'image/jpeg',
'image/png',
'image/svg+xml',
'image/tiff',
];
// not used here, but used in backend Dynamics config
// keeping here for reference as well:
const MINIFIED_MIME_TYPES = [
'text/csv',
'application/msword',
'application/vnd*',
'application/pdf',
'image/*',
];
const ALLOWED_FILE_TYPES = [
'.csv',
'.doc',
'.docx',
'.odt',
'.pdf',
'.xls',
'.xlsx',
'.ods',
'.gif',
'.jpeg',
'.jpg',
'.png',
'.svg',
'.tif',
];
export const CLAIM_FILE_UPLOAD_FIELDS = [
'quartech_completedmeetingandserviceprovisionlog',
'quartech_copyofconsultantfinalreportorbusinessplan',
'quartech_invoices',
'quartech_proofofpayment',
'quartech_businessplan',
'quartech_growthstrategy',
];
const FILE_UPLOAD_ID_SUFFIX = '_AttachFile';

// TODO: move to document step setup
// $(document).ready(function () {
// addFileUploadControls(CLAIM_FILE_UPLOAD_FIELDS);
// });

export function addFileUploadControls(fieldsForFileUploadControls) {
logger.info({
fn: addFileUploadControls,
message: 'Start initializing file upload controls',
data: {
fieldsForFileUploadControls,
},
});
fieldsForFileUploadControls.forEach((fieldName) => {
addFileUpload(fieldName);

disableField(fieldName);
});

addTitleToNotesControl();
}

function addTitleToNotesControl() {
$(`#notescontrol`).prepend(
'<div><h4>Documents Previously Uploaded</h4></div>'
);
}

function disableField(fieldName) {
$(`#${fieldName}`).attr('readonly', 'readonly');
}

// binary conversion of bytes
function formatBytes(bytes, decimals = 2, forceFormat, returnFloat = false) {
if (!+bytes) return '0 Bytes';

const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

let i;

if (forceFormat && sizes.includes(forceFormat)) {
i = sizes.indexOf(forceFormat);
} else {
i = Math.floor(Math.log(bytes) / Math.log(k));
}

const number = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));

if (returnFloat) {
return number;
}

return `${number} ${sizes[i]}`;
}

function validateFileUpload(file) {
const re = /(?:\.([^.]+))?$/; // regex to pull file extension string
const ext = re.exec(file.name)[1];

// note: microsoft seems to use binary system for byte conversion
const fileSizeInKB = formatBytes(file.size, 2, 'KB', true);

const isValidFileSize = fileSizeInKB <= MAXIMUM_FILE_SIZE_IN_KB; // 10 MB size limit
const isValidFileType = ALLOWED_FILE_TYPES.includes(`.${ext}`);

const isValidUpload = isValidFileSize && isValidFileType;

if (isValidUpload) {
return true;
}

let alertStr = '';
if (!isValidFileType && !isValidFileSize) {
alertStr = `Selected file(s) do not match the allowed file extensions and exceed file size limit of 10MB. Please upload a valid file size & file type of: ${ALLOWED_FILE_TYPES.join(
', '
)}.`;
} else if (!isValidFileType) {
alertStr = `Selected file(s) do not match the allowed file extensions. Please upload a file type of: ${ALLOWED_FILE_TYPES.join(
', '
)}.`;
} else if (!isValidFileSize) {
alertStr =
'Selected file(s) exceeds the allowed file upload limit of 10MB. Please upload a file with a size of 10MB or less.';
}

if (alertStr) {
alert(alertStr);
return false;
}

return false;
}

function addFileUpload(toFieldId) {
const fieldFileUploadId = toFieldId + FILE_UPLOAD_ID_SUFFIX;
logger.info({
fn: addFileUpload,
message: `Start addFileUpload toFieldId: ${toFieldId}`,
data: {
toFieldId,
fieldFileUploadId,
},
});
const fileUploadHtml = `<input type="file" multiple="multiple" id="${fieldFileUploadId}" accept="${ALLOWED_FILE_TYPES.join(
','
)}" aria-label="Attach files..." style='height: 50px; background: lightgrey; width: 100%; padding: 10px 0 0 10px;'>`;

const divControl = $(`#${toFieldId}`).parent();

divControl.append(fileUploadHtml);

$('#AttachFile').attr(
'accept',
ALLOWED_FILE_TYPES.join(',') + ',' + ALLOWED_MIME_TYPES.join(',')
);
$(`#${fieldFileUploadId}`).change(function (e) {
const targetFieldId = fieldFileUploadId.replace(FILE_UPLOAD_ID_SUFFIX, '');

let chosenFiles = '';
for (const i = 0; i < e.target.files.length; i++) {
const file = e.target.files[i];
const isValidFileUpload = validateFileUpload(file);

if (isValidFileUpload) {
chosenFiles += `${file.name} (${formatBytes(file.size)})\n`;
$(`#${targetFieldId}`).val(chosenFiles);
} else {
$(`#${fieldFileUploadId}`).val('');
$(`#${targetFieldId}`).val('');
}
}

updateOobFileUpload();
});
}

function updateOobFileUpload() {
let selectedFiles = [];

CLAIM_FILE_UPLOAD_FIELDS.forEach((fieldName) => {
let fileUploadId = fieldName + FILE_UPLOAD_ID_SUFFIX;

const fieldFileUploadCtr = document.getElementById(fileUploadId);

for (const i = 0; i < fieldFileUploadCtr.files.length; i++) {
const file = fieldFileUploadCtr.files[i];
selectedFiles.push(file);
}
});

const fileList = fileListFrom(selectedFiles);

const attachFileCtr = document.getElementById('AttachFile');
attachFileCtr.onchange = console.log;
attachFileCtr.files = fileList;

logger.info({
fn: updateOobFileUpload,
message: 'Set attach file control files attribute, attachFileCtr.files',
data: { fileList },
});
}

/** @params {File[]} files - Array of files to add to the FileList */
function fileListFrom(files) {
const b = new ClipboardEvent('').clipboardData || new DataTransfer();

for (const file of files) b.items.add(file);
return b.files;
}
42 changes: 26 additions & 16 deletions powerpod/src/js/claim/steps/documents.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { hideQuestion, observeIframeChanges } from '../../common/html.js';
import { getEnvVars } from '../../common/env.js';
import {
getProgramAbbreviation,
} from '../../common/program.ts';
import { getProgramAbbreviation } from '../../common/program.ts';
import { configureFields } from '../../common/fieldConfiguration.js';
import {
setFieldValue,
} from '../../common/html.js';
import { setFieldValue } from '../../common/html.js';
import { setFieldReadOnly } from '../../common/fieldValidation.js';
import {
CLAIM_FILE_UPLOAD_FIELDS,
addFileUploadControls,
} from '../documents.js';

export async function customizeDocumentsStep() {
configureFields();
// TODO: enable this for TASK 3631
// addFileUploadControls(CLAIM_FILE_UPLOAD_FIELDS);

const programAbbreviation = getProgramAbbreviation();

Expand Down Expand Up @@ -47,24 +49,32 @@ export async function customizeDocumentsStep() {
</div>
`;

$('fieldset[aria-label="Supporting Documents"]').after(beforeContinuingNoteHtmlContent);
$('fieldset[aria-label="Supporting Documents"]').after(
beforeContinuingNoteHtmlContent
);
}
}
}

async function addSatisfactionSurveyChefsIframe() {
$('#quartech_satisfactionsurveychefssubmissionid')?.closest('tr')?.css({ display: 'none' });

$('#quartech_satisfactionsurveychefssubmissionid')
?.closest('tr')
?.css({ display: 'none' });

setFieldReadOnly('quartech_satisfactionsurveyid');

const chefsSubmissionId = $('#quartech_satisfactionsurveychefssubmissionid')?.val();
const chefsSubmissionId = $(
'#quartech_satisfactionsurveychefssubmissionid'
)?.val();
let chefsUrl = '';

if (chefsSubmissionId) {
chefsUrl = `https://submit.digital.gov.bc.ca/app/form/success?s=${chefsSubmissionId}`;
} else {
const { quartech_ChefsNefbaSatisfactionSurveyFormId: chefsNefbaSatisfactionSurveyFormId } =
await getEnvVars();
const {
quartech_ChefsNefbaSatisfactionSurveyFormId:
chefsNefbaSatisfactionSurveyFormId,
} = await getEnvVars();

if (!chefsNefbaSatisfactionSurveyFormId) {
alert(
Expand All @@ -83,11 +93,11 @@ async function addSatisfactionSurveyChefsIframe() {

const submissionPayload = JSON.parse(event.data);

console.log(
'received submissionId: ' + submissionPayload.submissionId
);
console.log('received submissionId: ' + submissionPayload.submissionId);

$('#quartech_satisfactionsurveychefssubmissionid').val(submissionPayload.submissionId);
$('#quartech_satisfactionsurveychefssubmissionid').val(
submissionPayload.submissionId
);

const confirmationId = submissionPayload.submissionId
.substring(0, 8)
Expand Down
24 changes: 15 additions & 9 deletions powerpod/src/js/common/fieldValidation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
validateDemographicInfoRequiredFields,
validateIsConsultantEitherBciaOrCpa,
} from '../application/validation.js';
import { Form, FormStep, HtmlElementType } from './constants.js';
import { Environment, Form, FormStep, HtmlElementType } from './constants.js';
import { getEnv } from './env.ts';
import {
getFieldsBySectionClaim,
getFieldsBySectionApplication,
Expand Down Expand Up @@ -421,15 +422,20 @@ export function displayValidationErrors(validationErrorHtml) {

export function addValidationCheck(fieldName, validation) {
if (validation?.intervalBased) {
setInterval(() => validateStepFields(), 100);
} else {
$(`input[id*='${fieldName}']`).on(
validation?.event ?? 'onchange',
function () {
validateStepFields();
}
);
const env = getEnv();
// do not enable interval based on dev or test, since we only use it for Canada Post
// integration for now, it's only needed in production
if (env === Environment.PROD) {
setInterval(() => validateStepFields(), 100);
return;
}
}
$(`input[id*='${fieldName}']`).on(
validation?.event ?? 'onchange',
function () {
validateStepFields();
}
);
}

export function setInputMaxLength(fieldName, maxLength) {
Expand Down
Loading

0 comments on commit ae12164

Please sign in to comment.