Files
pedwfrontend/components/utils/index.js
T

826 lines
28 KiB
JavaScript

import { JSONPath as jsonpath } from "jsonpath-plus";
import { v4 as uuidv4 } from "uuid";
import {
getBasicPartSavedDetails,
getBasicSearchDetails,
getBasicSearchDetailsPaged
} from "../../actions/services/searchService";
import {
getPortalModuleDetailsProxy,
getPortalModuleDetails
} from "../../actions/services/caseService";
import data from "../../data/collections.json";
import xpath from "xpath";
/*
* Get the lookup collection by the appeal type entity
* @param String formtype - string from appeal entity name
*/
export const getFormCollection = (formtype) => {
const collectionName = jsonpath({
path: "$..[?(@ && @.LogicalName=='" + formtype + "')]",
json: data,
eval: true
});
return collectionName[0];
};
export const getFormCollectionByID = (appealTypeID) => {
const collectionName = jsonpath({
path: "$..[?(@ && @.appealTypeID =='" + appealTypeID + "')]",
json: data,
eval: true
});
return collectionName[0];
};
export const getNavigationPropertyByPrimaryAttribute = (primaryAttribute) => {
const collectionName = jsonpath({
path: "$..[?(@ && @.PrimaryIdAttribute =='" + primaryAttribute + "')]",
json: data,
eval: true
});
return collectionName[0];
};
export const getFormIDByLogicalName = (appealTypeLogicalName) => {
const collectionName = jsonpath({
path: "$..[?(@ && @.LogicalName =='" + appealTypeLogicalName + "')]",
json: data,
eval: true
});
return collectionName[0];
};
export const getPickListLabel = (data, picklistType, picklistID) => {
const pickListData = jsonpath({
path: "$..[?(@ && @.LogicalName=='" + picklistType + "')]",
json: data,
eval: true
});
const pickListLabel = jsonpath({
path:
"$..[?(@ && @.Value=='" +
picklistID +
"')].Label.LocalizedLabels..Label",
json: pickListData,
eval: true
});
return pickListLabel[0];
};
export const getRadioLabel = (data, radiotListName, radioListID) => {
const radioListData = jsonpath({
path: "$..[?(@ && @.LogicalName=='" + radiotListName + "')]",
json: data,
eval: true
});
const pickListLabel = jsonpath({
path:
"$..[?(@ && @.Value=='" +
radioListID +
"')].Label.LocalizedLabels..Label",
json: radioListData,
eval: true
});
return pickListLabel[0];
};
/*
* Get the details of a case from the appeal type
* @param object searchResultsObj
*/
export const getSearchDetails = async (searchResultsObj) => {
let detailsArr = [];
searchResultsObj = searchResultsObj.value;
const detailsObj = searchResultsObj.map((searchDetail, index) => {
let formMeta = getFormCollectionByID(
searchDetail.pinswg_appealcasetype
);
// console.log(
// "------------------- Details: ",
// formMeta.LogicalCollectionName,
// searchDetail.title,
// formMeta.PrimaryIdAttribute,
// searchDetail.incidentid,
// searchDetail.pinswg_appealcasetype
// );
if (searchDetail.pinswg_appealcasetype == null) {
detailsArr.push(
getBasicSearchDetails(
"pinswg_dnses",
searchDetail.title,
"pinswg_dnsid",
searchDetail.incidentid
) || {
"@odata.count": 1,
"value": [{ "title": searchDetail.title }]
}
);
} else {
// formMeta?.LogicalCollectionName &&
// formMeta?.LogicalCollectionName != "pinswg_sipses" &&
detailsArr.push(
getBasicSearchDetails(
formMeta.LogicalCollectionName,
searchDetail.title,
formMeta.PrimaryIdAttribute,
searchDetail.incidentid
) || {
"@odata.count": 1,
"value": [{ "title": searchDetail.title }]
}
);
}
});
// Promise.all(detailsArr).then((data) => {
// console.log(data);
// console.log(detailsArr);
// return data;
// });
return Promise.all(detailsArr);
};
/*
* Get the partially saved details of a case from the appeal type
* @param object searchResultsObj
*/
export const getPartSavedDetails = (searchResultsObj) => {
let detailsArr = [];
searchResultsObj = searchResultsObj.value;
const detailsObj = searchResultsObj.map((searchDetail, index) => {
if (searchDetail.pinswg_appealcasetype == null) {
console.log(searchDetail.title);
} else {
let formMeta = getFormCollectionByID(
searchDetail.pinswg_appealcasetype
);
// console.log(formMeta);
detailsArr.push(
getBasicPartSavedDetails(
formMeta.LogicalCollectionName,
searchDetail.title,
formMeta.PrimaryIdAttribute,
searchDetail.incidentid
)
);
}
});
return Promise.all(detailsArr);
};
/*
* Get the details of a case from the appeal type
* @param object searchResultsObj
*/
// export const getSearchDetailsPaged = (searchResultsObj) => {
// let detailsArr = [];
// searchResultsObj = searchResultsObj.value;
// const detailsObj = searchResultsObj.map((searchDetail, index) => {
// if (searchDetail.pinswg_appealcasetype == null) {
// console.log(searchDetail.title);
// } else {
// let formMeta = getFormCollectionByID(
// searchDetail.pinswg_appealcasetype
// );
// formMeta?.LogicalCollectionName &&
// formMeta?.LogicalCollectionName != "pinswg_sipses" &&
// detailsArr.push(
// getBasicSearchDetailsPaged(
// formMeta.LogicalCollectionName,
// searchDetail.title,
// formMeta.PrimaryIdAttribute,
// searchDetail.incidentid
// )
// );
// }
// });
// return Promise.all(detailsArr);
// };
// export const getSearchDetailsPaged = async (searchResultsObj) => {
// const searchResults = searchResultsObj.value;
// //Group incidents by appeal type
// const groupedByAppealType = {};
// searchResults.forEach((incident) => {
// const appealType = incident.pinswg_appealcasetype;
// if (!appealType) return;
// const formMeta = getFormCollectionByID(appealType);
// if (
// !formMeta?.LogicalCollectionName ||
// formMeta.LogicalCollectionName === "pinswg_sipses"
// )
// return;
// const key = formMeta.LogicalCollectionName;
// if (!groupedByAppealType[key]) groupedByAppealType[key] = [];
// groupedByAppealType[key].push({
// incidentID: incident.incidentid,
// caseReference: incident.title,
// primaryIdAttribute: formMeta.PrimaryIdAttribute,
// });
// });
// // Make all API calls in parallel per appeal type
// const allDetails = await Promise.all(
// Object.entries(groupedByAppealType).map(
// async ([appealTypeName, incidents]) => {
// console.log(
// `Fetching details for appeal type: ${appealTypeName}, incidents: ${incidents.length}`
// );
// // Fully parallel for each incident
// const results = await Promise.all(
// incidents.map((i) =>
// getBasicSearchDetailsPaged(
// appealTypeName,
// i.caseReference,
// i.primaryIdAttribute,
// i.incidentID
// ).catch((err) => {
// console.error(
// `Error fetching incident ${i.caseReference}:`,
// err
// );
// return null; // continue other calls even if one fails
// })
// )
// );
// return results.filter((r) => r); // remove nulls from failed calls
// }
// )
// );
// //Flatten all results into a single array
// return allDetails.flat();
// };
export const getSearchDetailsPaged = async (searchResultsObj) => {
searchResultsObj = searchResultsObj.value;
// Group incidents by appeal type
const groupedByAppealType = searchResultsObj.reduce((acc, detail) => {
const appealType = detail.pinswg_appealcasetype;
if (!appealType) {
console.log("No appeal type for:", detail.title);
return acc;
}
if (!acc[appealType]) acc[appealType] = [];
acc[appealType].push({
incidentID: detail.incidentid,
title: detail.title
});
return acc;
}, {});
const allDetails = [];
// For each appeal type, call getBasicSearchDetailsPaged once with all incident IDs
for (const [appealType, incidents] of Object.entries(groupedByAppealType)) {
const incidentIDs = incidents.map((i) => i.incidentID);
// Get the form meta for this appeal type to access primaryIdAttribute
const formMeta = getFormCollectionByID(appealType);
if (!formMeta || !formMeta.PrimaryIdAttribute) {
console.log(`Missing form metadata for appeal type: ${appealType}`);
continue;
}
// console.log(
// `Fetching ${incidentIDs.length} incidents for appeal type: ${appealType} with primaryIdAttribute: ${formMeta.PrimaryIdAttribute}`
// );
try {
const details = await getBasicSearchDetailsPaged(
formMeta.LogicalCollectionName, // appealTypeName
null, // caseReference is no longer used in batch
formMeta.PrimaryIdAttribute, // primaryIdAttribute
incidentIDs // pass array of incidentIDs
);
allDetails.push(...details);
} catch (err) {
consoleLogger(err);
}
}
return allDetails;
};
export const getProgressObj = (
formObjXML,
titleList,
mandatoryFieldsData,
props
) => {
const parser = new DOMParser();
const BuildFormObj = (formObjXML) => {
var doc = parser.parseFromString(formObjXML, "text/xml");
var tabs = xpath.select("//form/tabs/tab[*]", doc);
const formObj = Object.keys(tabs).map((key, index) => {
var sectionXML = xpath.select(
"//tabs/tab[" +
(index + 1) +
"]//rows/row/control[not(@parentField)]/..",
doc
);
return BuildRowObj(sectionXML, titleList[key].value);
});
const progressObj = Object.keys(formObj).map((key, index) => {
let fieldObj = formObj[key].fieldsrowObj;
let rowCount = 0;
!props.dirty &&
typeof props.initialValues != "undefined" &&
Object.keys(fieldObj).map((key, index) => {
fieldObj[key].datafieldname in props.initialValues &&
props.initialValues[fieldObj[key].datafieldname] !=
null &&
rowCount++;
});
props.dirty &&
Object.keys(fieldObj).map((key, index) => {
fieldObj[key].datafieldname in
props.props.form["appealForm"].values &&
props.props.form["appealForm"].values[
fieldObj[key].datafieldname
] != null &&
rowCount++;
});
return {
"title": titleList[key].value,
rowCount,
"totalFields": formObj[key].fieldsTotal,
"allFieldsComplete":
titleList[key].value == "Upload documents"
? (_.has(props.props.appealType.fileList, "value") &&
props.props.appealType.fileList.value.length >
0) ||
(_.has(props.props.form.appealForm, "values") &&
Object.keys(
props.props.form.appealForm.values
).filter((k) => k.startsWith("pinswg_fileUpload"))
.length > 0)
: rowCount == formObj[key].fieldsTotal
};
});
return progressObj;
};
const BuildRowObj = (rowXML, titleList) => {
let rowObj = Object.keys(rowXML).map((key, index) => {
var doc = parser.parseFromString(rowXML[key].outerHTML, "text/xml");
if (_.isEmpty(rowXML[key].innerHTML)) {
("");
} else {
var rows = xpath.select("//label/@description", doc);
var fieldtype = xpath.select("//@classid", doc);
var validation = xpath.select("//@validation", doc);
var datafieldname = xpath.select("//@datafieldname", doc);
var datafieldcontent = xpath.select("//@datafieldcontent", doc);
var parentField = xpath.select("//@parentField", doc);
var parentFieldShowOnValue = xpath.select(
"//@parentFieldShowOnValue",
doc
);
var requiredDocumentValue = xpath.select(
"//@requiredDocumentValue",
doc
);
var requiredDocumentLabel = xpath.select(
"//@requiredDocumentLabel",
doc
);
var hint = xpath.select("//label/@hint", doc);
var dateStart = xpath.select("//@dateStart", doc);
var dateEnd = xpath.select("//@dateEnd", doc);
hint = !_.isEmpty(hint) && hint[0].value;
validation = !_.isEmpty(validation) ? validation[0].value : [];
parentField = !_.isEmpty(parentField) && parentField[0].value;
parentFieldShowOnValue =
!_.isEmpty(parentFieldShowOnValue) &&
parentFieldShowOnValue[0].value;
datafieldcontent =
!_.isEmpty(datafieldcontent) && datafieldcontent[0].value;
requiredDocumentValue =
!_.isEmpty(requiredDocumentValue) &&
requiredDocumentValue[0].value;
requiredDocumentLabel =
!_.isEmpty(requiredDocumentLabel) &&
requiredDocumentLabel[0].value;
dateStart = !_.isEmpty(dateStart) && dateStart[0].value;
dateEnd = !_.isEmpty(dateEnd) && dateEnd[0].value;
const isRequiredField = jsonpath({
path:
"$..value[?(@ && @.LogicalName=='" +
datafieldname[0].value +
"')]",
json: mandatoryFieldsData,
eval: true
});
if (datafieldname[0].value.includes("pinswg_fileUpload")) {
if (typeof isRequiredField[0] != "undefined") {
if (isRequiredField[0].RequiredLevel.Value != "None") {
//console.log(datafieldname[0].value, validation);
return {
"fieldType": fieldtype[0].value,
"label": rows[0].value,
"datafieldname": datafieldname[0].value,
"datafieldcontent": datafieldcontent,
"validation": validation
};
}
} else {
return {
"fieldType": fieldtype[0].value,
"label": rows[0].value,
"datafieldname": datafieldname[0].value,
"key": key,
"picklistData": props.props.formData.pickListData,
"mandatoryFieldsData": mandatoryFieldsData
};
}
} else {
if (typeof isRequiredField[0] != "undefined") {
if (isRequiredField[0].RequiredLevel.Value != "None") {
//console.log(datafieldname[0].value, validation);
return {
"fieldType": fieldtype[0].value,
"label": rows[0].value,
"datafieldname": datafieldname[0].value,
"datafieldcontent": datafieldcontent,
"validation": validation
};
} else {
return null;
}
} else {
return null;
}
}
}
});
rowObj = rowObj.filter(function (el) {
return el != null;
});
rowObj = rowObj.filter(function (el) {
return typeof el.validation != "undefined";
});
rowObj = rowObj.filter(function (el) {
return el.validation.indexOf("required") > -1;
});
const filterUnwanted = (rowObj) => {
const required = rowObj.filter((el) => {
return !_.isEmpty(el.validation);
});
return required;
};
return {
"title": titleList,
"validationFieldsTotal": filterUnwanted(rowObj).length,
"fieldsTotal": rowObj.length,
"fieldsrowObj": rowObj
};
};
const progObj = BuildFormObj(formObjXML);
//console.log(progObj);
return progObj;
};
export const getTempCaseRef = () => {
function randomString(length) {
return Math.random().toString(36).substr(2, length);
}
const randomGUID = uuidv4();
return "TMP-" + randomString(5).toUpperCase();
};
export const getThumbnailIconByExtension = (blobName) => {
let fileType = blobName.slice(blobName.lastIndexOf(".") + 1);
switch (fileType) {
case "html":
return "/assets/images/documenttypes/html.png";
break;
case "txt":
return "/assets/images/documenttypes/txt.png";
break;
case "doc":
return "/assets/images/documenttypes/doc.png";
break;
case "pdf":
return "/assets/images/documenttypes/pdf.png";
break;
case "docx":
return "/assets/images/documenttypes/docx.png";
break;
case "csv":
return "/assets/images/documenttypes/csv.png";
break;
case "xlsx":
return "/assets/images/documenttypes/xlsx.png";
break;
case "zip":
return "/assets/images/documenttypes/zip.png";
break;
case "jpeg":
case "jpg":
return "/assets/images/documenttypes/jpg.png";
case "png":
return "/assets/images/documenttypes/png.png";
case "tiff":
case "tif":
return "/assets/images/documenttypes/tif.png";
break;
default:
return "/assets/images/documenttypes/default.png";
break;
}
};
export const bytesToSize = (bytes) => {
var sizes = ["Bytes", "KB", "MB", "GB", "TB"];
if (bytes == 0) return "0 Byte";
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + " " + sizes[i];
};
export const formatDates = (dateObj, showTime) => {
var dateObj = new Date(dateObj);
var dd = String(dateObj.getDate()).padStart(2, "0");
var mm = String(dateObj.getMonth() + 1).padStart(2, "0"); //January is 0!
var yyyy = dateObj.getFullYear();
var hh = dateObj.getHours();
hh = ("0" + hh).slice(-2);
var mins = dateObj.getMinutes();
mins = ("0" + mins).slice(-2);
const dateStr = showTime
? hh == 0 && mins == 0
? ""
: hh + ":" + mins
: dd + "/" + mm + "/" + yyyy + " ";
return dateStr;
};
export const getDetailsProxy = (resultsObj, detailsType) => {
let detailsArr = [];
resultsObj = resultsObj.value;
const detailsObj = resultsObj.map((searchDetail, index) => {
if (searchDetail.pinswg_appealcasetype == null) {
console.log(
detailsType != "myWatchedCases"
? searchDetail.ticketnumber
: searchDetail[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
]
);
} else {
detailsArr.push(
getPortalModuleDetailsProxy(
getFormCollectionByID(searchDetail.pinswg_appealcasetype)
.LogicalCollectionName,
detailsType != "myWatchedCases"
? searchDetail.ticketnumber
: searchDetail[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
]
)
);
}
});
return Promise.all(detailsArr);
};
export const getDocumentTypeFromFilename = (filename) => {
var doctypeCode = "000000";
if (typeof filename != "undefined") {
if (filename.indexOf("_-_Statement_of_Case") > 0)
doctypeCode = "000000";
else if (filename.indexOf("_-_Application_Form") > 0)
doctypeCode = "000001";
else if (filename.indexOf("_-_Site_Ownership_Certificate") > 0)
doctypeCode = "000002";
else if (filename.indexOf("_-_Decision_Notice") > 0)
doctypeCode = "000003";
else if (filename.indexOf("_-_Site_Location_Plan") > 0)
doctypeCode = "000004";
else if (filename.indexOf("_-_Plans_Drawing_Documents") > 0)
doctypeCode = "000005";
else if (filename.indexOf("_-_Additional_Plans_Drawings_Documents") > 0)
doctypeCode = "000006";
else if (filename.indexOf("_-_Design_and_Access_Statement") > 0)
doctypeCode = "000007";
else if (filename.indexOf("_-_NSB_LPA_Additional_Documents") > 0)
doctypeCode = "000008";
else if (filename.indexOf("_-_LPA_Correspondence") > 0)
doctypeCode = "000009";
else if (filename.indexOf("_-_LPA_Original_Permission") > 0)
doctypeCode = "000010";
else if (filename.indexOf("_-_LPA's_Registration_Letter") > 0)
doctypeCode = "000011";
else if (filename.indexOf("_-_Environmental_Statement") > 0)
doctypeCode = "000012";
else if (filename.indexOf("_-_Cost_of_Application") > 0)
doctypeCode = "000013";
else if (filename.indexOf("_-_Other_Relevant_Material") > 0)
doctypeCode = "000014";
else if (
filename.indexOf("_-_S106_Agreement_or_Unilateral_Undertaking") > 0
)
doctypeCode = "000015";
}
return doctypeCode;
};
export const updateLinks = (input) => {
const EMPTY_QUILL_PARAGRAPHS_REGEX =
/<p[^>]*>\s*(?:<br\s*\/?>|&nbsp;|\s)*\s*<\/p>/gi;
const URL_REGEX = /\b(https?:\/\/[^\s<]+)/gi;
const stripTrailingUrlPunctuation = (url) => {
let cleanUrl = url;
let trailing = "";
while (/[.,!?;:'"]$/.test(cleanUrl)) {
trailing = cleanUrl.slice(-1) + trailing;
cleanUrl = cleanUrl.slice(0, -1);
}
const pairs = [
[")", "("],
["]", "["],
["}", "{"]
];
let changed = true;
while (changed && cleanUrl) {
changed = false;
for (const [close, open] of pairs) {
if (cleanUrl.endsWith(close)) {
const openCount = (
cleanUrl.match(new RegExp(`\\${open}`, "g")) || []
).length;
const closeCount = (
cleanUrl.match(new RegExp(`\\${close}`, "g")) || []
).length;
if (closeCount > openCount) {
trailing = close + trailing;
cleanUrl = cleanUrl.slice(0, -1);
changed = true;
}
}
}
}
return { cleanUrl, trailing };
};
const processHtmlString = (htmlString) => {
if (typeof htmlString !== "string" || !htmlString) return htmlString;
let html = htmlString.replace(EMPTY_QUILL_PARAGRAPHS_REGEX, "");
const anchorPlaceholders = [];
html = html.replace(/<a\b[^>]*>[\s\S]*?<\/a>/gi, (match) => {
const token = `__ANCHOR_PLACEHOLDER_${anchorPlaceholders.length}__`;
anchorPlaceholders.push(match);
return token;
});
html = html.replace(URL_REGEX, (match) => {
const { cleanUrl, trailing } = stripTrailingUrlPunctuation(match);
if (!cleanUrl) return match;
return `<a href="${cleanUrl}" target="_blank" rel="noopener noreferrer">${cleanUrl}</a>${trailing}`;
});
html = html.replace(/__ANCHOR_PLACEHOLDER_(\d+)__/g, (_, index) => {
return anchorPlaceholders[Number(index)];
});
return html;
};
if (typeof input === "string") {
return processHtmlString(input);
}
if (!input || typeof input !== "object" || Array.isArray(input)) {
return input;
}
const updated = { ...input };
for (const key in updated) {
if (Object.prototype.hasOwnProperty.call(updated, key)) {
const value = updated[key];
if (typeof value === "string") {
updated[key] = processHtmlString(value);
}
}
}
return updated;
};
export const whichRepType = (props, locale) => {
let repType;
let whichBaseType =
props.currentView?.caseReference.repDetails.representationType ||
formObj.representationForm.values.representationType;
switch (whichBaseType) {
case "Statement":
repType = locale == "cy" ? "Datganiad" : "Statment";
break;
case "Questionnaire":
repType = locale == "cy" ? "Holiadur" : "Questionnaire";
break;
case "Final comments":
repType = locale == "cy" ? "Sylwadau terfynol" : "Final comments";
break;
default:
// code block
}
return repType;
};
export const getDocLink = (docsOffline) => {
var startTime = docsOffline.split(",")[0];
var endTime = docsOffline.split(",")[1];
// console.log(startTime);
// console.log(endTime);
var currentDate = new Date();
var startDate = new Date(currentDate.getTime());
startDate.setHours(startTime.split(":")[0]);
startDate.setMinutes(startTime.split(":")[1]);
startDate.setSeconds(startTime.split(":")[2]);
var endDate = new Date(currentDate.getTime());
endDate.setHours(endTime.split(":")[0]);
endDate.setMinutes(endTime.split(":")[1]);
endDate.setSeconds(endTime.split(":")[2]);
// console.log(startDate);
// console.log(endDate);
// console.log(currentDate);
var valid = startDate < currentDate && endDate > currentDate;
return valid;
};