Merged PR 2153: fix for pdf formatting and hyperlinks

fix for pdf formatting and hyperlinks

Related work items: #21897, #21898
This commit is contained in:
Robert Bond
2026-03-09 13:13:04 +00:00
4 changed files with 241 additions and 221 deletions
@@ -735,6 +735,12 @@ export const RenderMultiline = ({
input.onChange(valStr); input.onChange(valStr);
}; };
const handleBlur = () => {
const updated = updateLinks(editValue);
setEditValue(updated);
input.onChange(updated);
};
var modules = { var modules = {
toolbar: [ toolbar: [
[{ "header": [1, 2, false] }], [{ "header": [1, 2, false] }],
@@ -765,6 +771,7 @@ export const RenderMultiline = ({
theme="snow" theme="snow"
value={editValue} value={editValue}
onChange={changeEdit} onChange={changeEdit}
onBlur={handleBlur}
/> />
<textarea <textarea
{...input} {...input}
@@ -796,11 +803,16 @@ export const RenderRichMultiline = ({
); );
const changeEdit = (valStr) => { const changeEdit = (valStr) => {
valStr = updateLinks(valStr);
setEditValue(valStr); setEditValue(valStr);
input.onChange(valStr); input.onChange(valStr);
}; };
const handleBlur = () => {
const updated = updateLinks(editValue);
setEditValue(updated);
input.onChange(updated);
};
var modules = { var modules = {
toolbar: [ toolbar: [
[{ "header": [1, 2, false] }], [{ "header": [1, 2, false] }],
@@ -820,6 +832,7 @@ export const RenderRichMultiline = ({
theme="snow" theme="snow"
value={editValue} value={editValue}
onChange={changeEdit} onChange={changeEdit}
onBlur={handleBlur}
/> />
<textarea <textarea
{...input} {...input}
+7
View File
@@ -479,6 +479,12 @@ export const RenderRichMultiline = ({
input.onChange(valStr); input.onChange(valStr);
}; };
const handleBlur = () => {
const updated = updateLinks(editValue);
setEditValue(updated);
input.onChange(updated);
};
var modules = { var modules = {
toolbar: [ toolbar: [
[{ "header": [1, 2, false] }], [{ "header": [1, 2, false] }],
@@ -513,6 +519,7 @@ export const RenderRichMultiline = ({
theme="snow" theme="snow"
value={editValue} value={editValue}
onChange={changeEdit} onChange={changeEdit}
onBlur={handleBlur}
/> />
<textarea <textarea
{...input} {...input}
+105 -106
View File
@@ -5,7 +5,7 @@ import {
StyleSheet, StyleSheet,
Text, Text,
View, View,
Font, Font
} from "@react-pdf/renderer"; } from "@react-pdf/renderer";
import Html from "react-pdf-html"; import Html from "react-pdf-html";
import { getFormCollectionByID, bytesToSize } from "../../components/utils"; import { getFormCollectionByID, bytesToSize } from "../../components/utils";
@@ -27,16 +27,16 @@ const styles = StyleSheet.create({
backgroundColor: "white", backgroundColor: "white",
padding: 20, padding: 20,
fontSize: 16, fontSize: 16,
paddingBottom: 50, paddingBottom: 50
}, },
header: { header: {
fontSize: 25, fontSize: 25,
fontFamily: "Helvetica", fontFamily: "Helvetica",
flexDirection: "row", flexDirection: "row",
justifyContent: "space-between", justifyContent: "space-between"
}, },
subHeader: { subHeader: {
fontSize: 20, fontSize: 20
}, },
logoImage: { width: "200pt" }, logoImage: { width: "200pt" },
questionBullet: { width: "5%", fontSize: 12 }, questionBullet: { width: "5%", fontSize: 12 },
@@ -51,7 +51,7 @@ const styles = StyleSheet.create({
border: 1, border: 1,
borderColor: "#eee", borderColor: "#eee",
paddingLeft: 10, paddingLeft: 10,
backgroundColor: "white", backgroundColor: "white"
}, },
questionAnswerSmall: { questionAnswerSmall: {
color: "#757575", color: "#757575",
@@ -63,7 +63,7 @@ const styles = StyleSheet.create({
paddingLeft: 10, paddingLeft: 10,
paddingRight: 10, paddingRight: 10,
backgroundColor: "white", backgroundColor: "white",
marginRight: 10, marginRight: 10
}, },
questionAnswerSmaller: { questionAnswerSmaller: {
color: "#757575", color: "#757575",
@@ -73,7 +73,7 @@ const styles = StyleSheet.create({
border: 1, border: 1,
borderColor: "#eee", borderColor: "#eee",
paddingLeft: 10, paddingLeft: 10,
backgroundColor: "white", backgroundColor: "white"
}, },
questionAnswerMid: { questionAnswerMid: {
color: "#757575", color: "#757575",
@@ -83,7 +83,7 @@ const styles = StyleSheet.create({
border: 1, border: 1,
borderColor: "#eee", borderColor: "#eee",
paddingLeft: 10, paddingLeft: 10,
backgroundColor: "white", backgroundColor: "white"
}, },
questionAnswerWide: { questionAnswerWide: {
color: "#757575", color: "#757575",
@@ -92,7 +92,7 @@ const styles = StyleSheet.create({
border: 1, border: 1,
borderColor: "#eee", borderColor: "#eee",
backgroundColor: "white", backgroundColor: "white",
padding: 5, padding: 5
}, },
questionAnswerFull: { questionAnswerFull: {
@@ -102,13 +102,13 @@ const styles = StyleSheet.create({
padding: 5, padding: 5,
border: 1, border: 1,
borderColor: "#eee", borderColor: "#eee",
backgroundColor: "white", backgroundColor: "white"
}, },
sectionContainer: { sectionContainer: {
backgroundColor: "#F8F8F8", backgroundColor: "#F8F8F8",
padding: 10, padding: 10,
marginTop: 20, marginTop: 20,
fontSize: 15, fontSize: 15
}, },
pageNumber: { pageNumber: {
position: "absolute", position: "absolute",
@@ -117,13 +117,13 @@ const styles = StyleSheet.create({
left: 0, left: 0,
right: 0, right: 0,
textAlign: "center", textAlign: "center",
color: "grey", color: "grey"
}, },
richArea: { richArea: {
fontSize: 12, fontSize: 12,
flexDirection: "column", flexDirection: "column"
}, }
}); });
export const lpaQuestionnaire_pdf = ({ docProps }) => { export const lpaQuestionnaire_pdf = ({ docProps }) => {
@@ -145,16 +145,15 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
Font.registerHyphenationCallback((word) => [word]); Font.registerHyphenationCallback((word) => [word]);
function CleanHTML(htmlStr) { function CleanHTML(html = "") {
let cleanStr = if (typeof html !== "string") return "";
typeof htmlStr === "string"
? htmlStr.replace(
/<p><br><\/p>|<p class=\"ql-align-justify\"><br><\/p>/g,
""
)
: "";
return cleanStr; return html
.replace(/&nbsp;/gi, " ")
.replace(/<(p|div)([^>]*)>\s*(<br\s*\/?>)?\s*<\/\1>/gi, "")
.replace(/<p([^>]*)>\s*<\/p>/gi, "")
.replace(/(<br\s*\/?>\s*){3,}/gi, "<br /><br />")
.trim();
} }
return ( return (
@@ -166,7 +165,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<Text <Text
style={{ style={{
width: "60%", width: "60%",
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
{getTrans( {getTrans(
@@ -180,7 +179,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
width: "60%", width: "60%",
fontSize: 15, fontSize: 15,
marginTop: 20, marginTop: 20,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
{getTrans( {getTrans(
@@ -205,7 +204,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text style={{ fontSize: 14 }}> <Text style={{ fontSize: 14 }}>
@@ -220,7 +219,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>1.</Text> <Text style={styles.questionBullet}>1.</Text>
@@ -238,7 +237,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>2.</Text> <Text style={styles.questionBullet}>2.</Text>
@@ -256,7 +255,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>3.</Text> <Text style={styles.questionBullet}>3.</Text>
@@ -274,7 +273,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>4.</Text> <Text style={styles.questionBullet}>4.</Text>
@@ -294,7 +293,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text style={{ fontSize: 14 }}> <Text style={{ fontSize: 14 }}>
@@ -308,7 +307,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
@@ -316,7 +315,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -347,7 +346,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>6.</Text> <Text style={styles.questionBullet}>6.</Text>
@@ -365,14 +364,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -404,14 +403,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -442,14 +441,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -478,14 +477,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -511,7 +510,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text style={{ fontSize: 14 }}> <Text style={{ fontSize: 14 }}>
@@ -525,7 +524,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
@@ -533,7 +532,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -555,14 +554,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -584,13 +583,13 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -613,7 +612,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>14.</Text> <Text style={styles.questionBullet}>14.</Text>
@@ -634,7 +633,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text style={{ fontSize: 14 }}> <Text style={{ fontSize: 14 }}>
@@ -649,7 +648,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>15.</Text> <Text style={styles.questionBullet}>15.</Text>
@@ -666,14 +665,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -700,14 +699,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -736,14 +735,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -772,14 +771,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -806,14 +805,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -842,14 +841,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -879,7 +878,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>22.</Text> <Text style={styles.questionBullet}>22.</Text>
@@ -896,14 +895,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -936,7 +935,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text style={{ fontSize: 14 }}> <Text style={{ fontSize: 14 }}>
@@ -951,7 +950,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}>24.</Text> <Text style={styles.questionBullet}>24.</Text>
@@ -966,7 +965,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}></Text> <Text style={styles.questionBullet}></Text>
@@ -985,14 +984,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}></Text> <Text style={styles.questionBullet}></Text>
@@ -1023,7 +1022,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}></Text> <Text style={styles.questionBullet}></Text>
@@ -1041,7 +1040,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}></Text> <Text style={styles.questionBullet}></Text>
@@ -1058,14 +1057,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1098,7 +1097,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
wrap={false} wrap={false}
> >
@@ -1113,14 +1112,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1151,14 +1150,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1189,14 +1188,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1229,14 +1228,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1263,14 +1262,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1302,14 +1301,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1338,14 +1337,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1374,14 +1373,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
// wrap={false} // wrap={false}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionBullet}> <Text style={styles.questionBullet}>
@@ -1413,7 +1412,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text> <Text>
@@ -1429,14 +1428,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10,
alignItems: "center", alignItems: "center"
}} }}
> >
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10,
alignItems: "center", alignItems: "center"
}} }}
> >
<Text <Text
@@ -1459,7 +1458,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
border: 1, border: 1,
borderColor: "#eee", borderColor: "#eee",
backgroundColor: "white", backgroundColor: "white",
paddingRight: 10, paddingRight: 10
}} }}
wrap={true} wrap={true}
> >
@@ -1470,7 +1469,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10,
alignItems: "center", alignItems: "center"
}} }}
> >
<Text <Text
@@ -1480,7 +1479,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
? "60" ? "60"
: "40", : "40",
fontSize: 12, fontSize: 12,
marginLeft: 10, marginLeft: 10
}} }}
> >
{getTrans( {getTrans(
@@ -1498,7 +1497,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10,
alignItems: "center", alignItems: "center"
}} }}
> >
<Text style={{ width: "18%", fontSize: 12 }}> <Text style={{ width: "18%", fontSize: 12 }}>
@@ -1516,7 +1515,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={{ style={{
marginTop: 10, marginTop: 10,
fontFamily: "Helvetica-Bold", fontFamily: "Helvetica-Bold"
}} }}
> >
<Text style={{ fontSize: 14 }}> <Text style={{ fontSize: 14 }}>
@@ -1531,14 +1530,14 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
wrap={false} wrap={false}
style={{ style={{
flexDirection: "column", flexDirection: "column",
marginBottom: 10, marginBottom: 10
}} }}
> >
<View <View
wrap={false} wrap={false}
style={{ style={{
flexDirection: "row", flexDirection: "row",
marginBottom: 10, marginBottom: 10
}} }}
> >
<Text style={styles.questionTextWide}> <Text style={styles.questionTextWide}>
@@ -1551,7 +1550,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
<View <View
style={[ style={[
styles.questionAnswerFull, styles.questionAnswerFull,
{ flexDirection: "column" }, { flexDirection: "column" }
]} ]}
> >
{values.hasOwnProperty("filesList") && {values.hasOwnProperty("filesList") &&
@@ -1562,7 +1561,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
style={{ style={{
flexDirection: flexDirection:
"row", "row",
marginBottom: 4, marginBottom: 4
}} }}
> >
<Text <Text
@@ -1614,7 +1613,7 @@ export const lpaQuestionnaire_pdf = ({ docProps }) => {
borderColor: "#eee", borderColor: "#eee",
padding: 20, padding: 20,
paddingTop: 30, paddingTop: 30,
height: "100%", height: "100%"
}} }}
></View> ></View>
</Page> </Page>
+115 -114
View File
@@ -5,7 +5,7 @@ import {
getBasicSearchDetails, getBasicSearchDetails,
getBasicSearchDetailsPaged, getBasicSearchDetailsPaged,
getPortalModuleDetailsProxy, getPortalModuleDetailsProxy,
getPortalModuleDetails, getPortalModuleDetails
} from "../../actions"; } from "../../actions";
import data from "../../data/collections.json"; import data from "../../data/collections.json";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@@ -20,7 +20,7 @@ export const getFormCollection = (formtype) => {
const collectionName = jsonpath({ const collectionName = jsonpath({
path: "$..[?(@ && @.LogicalName=='" + formtype + "')]", path: "$..[?(@ && @.LogicalName=='" + formtype + "')]",
json: data, json: data,
eval: true, eval: true
}); });
return collectionName[0]; return collectionName[0];
}; };
@@ -29,7 +29,7 @@ export const getFormCollectionByID = (appealTypeID) => {
const collectionName = jsonpath({ const collectionName = jsonpath({
path: "$..[?(@ && @.appealTypeID =='" + appealTypeID + "')]", path: "$..[?(@ && @.appealTypeID =='" + appealTypeID + "')]",
json: data, json: data,
eval: true, eval: true
}); });
return collectionName[0]; return collectionName[0];
}; };
@@ -38,7 +38,7 @@ export const getNavigationPropertyByPrimaryAttribute = (primaryAttribute) => {
const collectionName = jsonpath({ const collectionName = jsonpath({
path: "$..[?(@ && @.PrimaryIdAttribute =='" + primaryAttribute + "')]", path: "$..[?(@ && @.PrimaryIdAttribute =='" + primaryAttribute + "')]",
json: data, json: data,
eval: true, eval: true
}); });
return collectionName[0]; return collectionName[0];
}; };
@@ -47,7 +47,7 @@ export const getFormIDByLogicalName = (appealTypeLogicalName) => {
const collectionName = jsonpath({ const collectionName = jsonpath({
path: "$..[?(@ && @.LogicalName =='" + appealTypeLogicalName + "')]", path: "$..[?(@ && @.LogicalName =='" + appealTypeLogicalName + "')]",
json: data, json: data,
eval: true, eval: true
}); });
return collectionName[0]; return collectionName[0];
}; };
@@ -56,7 +56,7 @@ export const getPickListLabel = (data, picklistType, picklistID) => {
const pickListData = jsonpath({ const pickListData = jsonpath({
path: "$..[?(@ && @.LogicalName=='" + picklistType + "')]", path: "$..[?(@ && @.LogicalName=='" + picklistType + "')]",
json: data, json: data,
eval: true, eval: true
}); });
const pickListLabel = jsonpath({ const pickListLabel = jsonpath({
@@ -66,7 +66,7 @@ export const getPickListLabel = (data, picklistType, picklistID) => {
"')].Label.LocalizedLabels..Label", "')].Label.LocalizedLabels..Label",
json: pickListData, json: pickListData,
eval: true, eval: true
}); });
return pickListLabel[0]; return pickListLabel[0];
}; };
@@ -75,7 +75,7 @@ export const getRadioLabel = (data, radiotListName, radioListID) => {
const radioListData = jsonpath({ const radioListData = jsonpath({
path: "$..[?(@ && @.LogicalName=='" + radiotListName + "')]", path: "$..[?(@ && @.LogicalName=='" + radiotListName + "')]",
json: data, json: data,
eval: true, eval: true
}); });
const pickListLabel = jsonpath({ const pickListLabel = jsonpath({
@@ -85,7 +85,7 @@ export const getRadioLabel = (data, radiotListName, radioListID) => {
"')].Label.LocalizedLabels..Label", "')].Label.LocalizedLabels..Label",
json: radioListData, json: radioListData,
eval: true, eval: true
}); });
return pickListLabel[0]; return pickListLabel[0];
}; };
@@ -100,7 +100,7 @@ export const getSearchDetails = async (searchResultsObj) => {
searchResultsObj = searchResultsObj.value; searchResultsObj = searchResultsObj.value;
const detailsObj = searchResultsObj.map((searchDetail, index) => { const detailsObj = searchResultsObj.map((searchDetail, index) => {
let formMeta = getFormCollectionByID( let formMeta = getFormCollectionByID(
searchDetail.pinswg_appealcasetype, searchDetail.pinswg_appealcasetype
); );
// console.log( // console.log(
// "------------------- Details: ", // "------------------- Details: ",
@@ -117,11 +117,11 @@ export const getSearchDetails = async (searchResultsObj) => {
"pinswg_dnses", "pinswg_dnses",
searchDetail.title, searchDetail.title,
"pinswg_dnsid", "pinswg_dnsid",
searchDetail.incidentid, searchDetail.incidentid
) || { ) || {
"@odata.count": 1, "@odata.count": 1,
"value": [{ "title": searchDetail.title }], "value": [{ "title": searchDetail.title }]
}, }
); );
} else { } else {
// formMeta?.LogicalCollectionName && // formMeta?.LogicalCollectionName &&
@@ -131,11 +131,11 @@ export const getSearchDetails = async (searchResultsObj) => {
formMeta.LogicalCollectionName, formMeta.LogicalCollectionName,
searchDetail.title, searchDetail.title,
formMeta.PrimaryIdAttribute, formMeta.PrimaryIdAttribute,
searchDetail.incidentid, searchDetail.incidentid
) || { ) || {
"@odata.count": 1, "@odata.count": 1,
"value": [{ "title": searchDetail.title }], "value": [{ "title": searchDetail.title }]
}, }
); );
} }
}); });
@@ -159,7 +159,7 @@ export const getPartSavedDetails = (searchResultsObj) => {
console.log(searchDetail.title); console.log(searchDetail.title);
} else { } else {
let formMeta = getFormCollectionByID( let formMeta = getFormCollectionByID(
searchDetail.pinswg_appealcasetype, searchDetail.pinswg_appealcasetype
); );
// console.log(formMeta); // console.log(formMeta);
detailsArr.push( detailsArr.push(
@@ -167,8 +167,8 @@ export const getPartSavedDetails = (searchResultsObj) => {
formMeta.LogicalCollectionName, formMeta.LogicalCollectionName,
searchDetail.title, searchDetail.title,
formMeta.PrimaryIdAttribute, formMeta.PrimaryIdAttribute,
searchDetail.incidentid, searchDetail.incidentid
), )
); );
} }
}); });
@@ -279,7 +279,7 @@ export const getSearchDetailsPaged = async (searchResultsObj) => {
if (!acc[appealType]) acc[appealType] = []; if (!acc[appealType]) acc[appealType] = [];
acc[appealType].push({ acc[appealType].push({
incidentID: detail.incidentid, incidentID: detail.incidentid,
title: detail.title, title: detail.title
}); });
return acc; return acc;
}, {}); }, {});
@@ -307,7 +307,7 @@ export const getSearchDetailsPaged = async (searchResultsObj) => {
formMeta.LogicalCollectionName, // appealTypeName formMeta.LogicalCollectionName, // appealTypeName
null, // caseReference is no longer used in batch null, // caseReference is no longer used in batch
formMeta.PrimaryIdAttribute, // primaryIdAttribute formMeta.PrimaryIdAttribute, // primaryIdAttribute
incidentIDs, // pass array of incidentIDs incidentIDs // pass array of incidentIDs
); );
allDetails.push(...details); allDetails.push(...details);
@@ -323,7 +323,7 @@ export const getProgressObj = (
formObjXML, formObjXML,
titleList, titleList,
mandatoryFieldsData, mandatoryFieldsData,
props, props
) => { ) => {
const parser = new DOMParser(); const parser = new DOMParser();
const BuildFormObj = (formObjXML) => { const BuildFormObj = (formObjXML) => {
@@ -336,7 +336,7 @@ export const getProgressObj = (
"//tabs/tab[" + "//tabs/tab[" +
(index + 1) + (index + 1) +
"]//rows/row/control[not(@parentField)]/..", "]//rows/row/control[not(@parentField)]/..",
doc, doc
); );
return BuildRowObj(sectionXML, titleList[key].value); return BuildRowObj(sectionXML, titleList[key].value);
@@ -376,10 +376,10 @@ export const getProgressObj = (
0) || 0) ||
(_.has(props.props.form.appealForm, "values") && (_.has(props.props.form.appealForm, "values") &&
Object.keys( Object.keys(
props.props.form.appealForm.values, props.props.form.appealForm.values
).filter((k) => k.startsWith("pinswg_fileUpload")) ).filter((k) => k.startsWith("pinswg_fileUpload"))
.length > 0) .length > 0)
: rowCount == formObj[key].fieldsTotal, : rowCount == formObj[key].fieldsTotal
}; };
}); });
@@ -401,17 +401,17 @@ export const getProgressObj = (
var parentFieldShowOnValue = xpath.select( var parentFieldShowOnValue = xpath.select(
"//@parentFieldShowOnValue", "//@parentFieldShowOnValue",
doc, doc
); );
var requiredDocumentValue = xpath.select( var requiredDocumentValue = xpath.select(
"//@requiredDocumentValue", "//@requiredDocumentValue",
doc, doc
); );
var requiredDocumentLabel = xpath.select( var requiredDocumentLabel = xpath.select(
"//@requiredDocumentLabel", "//@requiredDocumentLabel",
doc, doc
); );
var hint = xpath.select("//label/@hint", doc); var hint = xpath.select("//label/@hint", doc);
@@ -449,7 +449,7 @@ export const getProgressObj = (
datafieldname[0].value + datafieldname[0].value +
"')]", "')]",
json: mandatoryFieldsData, json: mandatoryFieldsData,
eval: true, eval: true
}); });
if (datafieldname[0].value.includes("pinswg_fileUpload")) { if (datafieldname[0].value.includes("pinswg_fileUpload")) {
@@ -461,7 +461,7 @@ export const getProgressObj = (
"label": rows[0].value, "label": rows[0].value,
"datafieldname": datafieldname[0].value, "datafieldname": datafieldname[0].value,
"datafieldcontent": datafieldcontent, "datafieldcontent": datafieldcontent,
"validation": validation, "validation": validation
}; };
} }
} else { } else {
@@ -471,7 +471,7 @@ export const getProgressObj = (
"datafieldname": datafieldname[0].value, "datafieldname": datafieldname[0].value,
"key": key, "key": key,
"picklistData": props.props.formData.pickListData, "picklistData": props.props.formData.pickListData,
"mandatoryFieldsData": mandatoryFieldsData, "mandatoryFieldsData": mandatoryFieldsData
}; };
} }
} else { } else {
@@ -483,7 +483,7 @@ export const getProgressObj = (
"label": rows[0].value, "label": rows[0].value,
"datafieldname": datafieldname[0].value, "datafieldname": datafieldname[0].value,
"datafieldcontent": datafieldcontent, "datafieldcontent": datafieldcontent,
"validation": validation, "validation": validation
}; };
} else { } else {
return null; return null;
@@ -518,7 +518,7 @@ export const getProgressObj = (
"title": titleList, "title": titleList,
"validationFieldsTotal": filterUnwanted(rowObj).length, "validationFieldsTotal": filterUnwanted(rowObj).length,
"fieldsTotal": rowObj.length, "fieldsTotal": rowObj.length,
"fieldsrowObj": rowObj, "fieldsrowObj": rowObj
}; };
}; };
@@ -616,7 +616,7 @@ export const getDetailsProxy = (resultsObj, detailsType) => {
? searchDetail.ticketnumber ? searchDetail.ticketnumber
: searchDetail[ : searchDetail[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue" "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
], ]
); );
} else { } else {
detailsArr.push( detailsArr.push(
@@ -627,8 +627,8 @@ export const getDetailsProxy = (resultsObj, detailsType) => {
? searchDetail.ticketnumber ? searchDetail.ticketnumber
: searchDetail[ : searchDetail[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue" "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
], ]
), )
); );
} }
}); });
@@ -678,98 +678,99 @@ export const getDocumentTypeFromFilename = (filename) => {
return doctypeCode; return doctypeCode;
}; };
export const updateLinks = (jsonObj) => { export const updateLinks = (input) => {
const parser = new DOMParser(); const EMPTY_QUILL_PARAGRAPHS_REGEX =
/<p[^>]*>\s*(?:<br\s*\/?>|&nbsp;|\s)*\s*<\/p>/gi;
// Function to process the HTML string and replace URLs with <a> tags const URL_REGEX = /\b(https?:\/\/[^\s<]+)/gi;
const processHtmlString = (htmlString) => {
const doc = parser.parseFromString(htmlString, "text/html");
// Find all text nodes in the document const stripTrailingUrlPunctuation = (url) => {
const walk = (node) => { let cleanUrl = url;
if (node.nodeType === Node.TEXT_NODE) { let trailing = "";
const urlRegex =
/(?:https?:\/\/)?(?:www\.)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})(\/[^\s]*)?/g;
let match;
let currentText = node.textContent;
let lastIndex = 0;
let newNodeContent = [];
// Process all URLs found in the current text node while (/[.,!?;:'"]$/.test(cleanUrl)) {
while ((match = urlRegex.exec(currentText)) !== null) { trailing = cleanUrl.slice(-1) + trailing;
// Before the URL cleanUrl = cleanUrl.slice(0, -1);
if (match.index > lastIndex) { }
newNodeContent.push(
currentText.slice(lastIndex, match.index), 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;
} }
// Construct the full URL (default to https://)
let fullUrl = match[0];
if (
!fullUrl.startsWith("http://") &&
!fullUrl.startsWith("https://")
) {
fullUrl = `https://${match[1]}${match[2] || ""}`; // Default to https
}
// Create the anchor element
const anchor = document.createElement("a");
anchor.href = fullUrl;
anchor.textContent = match[0];
anchor.target = "_blank";
anchor.setAttribute("rel", "noopener noreferrer");
// Add the anchor tag to the node content
newNodeContent.push(anchor);
// Update the last index processed
lastIndex = urlRegex.lastIndex;
}
// Add the remaining text after the last URL
if (lastIndex < currentText.length) {
newNodeContent.push(currentText.slice(lastIndex));
}
// If there were any replacements, update the text node
if (newNodeContent.length > 0) {
const fragment = document.createDocumentFragment();
newNodeContent.forEach((item) => {
if (typeof item === "string") {
fragment.appendChild(document.createTextNode(item));
} else {
fragment.appendChild(item);
}
});
node.parentNode.replaceChild(fragment, node);
} }
} }
}
// Traverse child nodes return { cleanUrl, trailing };
for (let i = 0; i < node.childNodes.length; i++) {
walk(node.childNodes[i]);
}
};
walk(doc.body);
return doc.body.innerHTML;
}; };
// Iterate over the JSON object and process values that are strings (HTML content) const processHtmlString = (htmlString) => {
for (const key in jsonObj) { if (typeof htmlString !== "string" || !htmlString) return htmlString;
if (jsonObj.hasOwnProperty(key)) {
const value = jsonObj[key];
// If the value is a string and contains HTML, process it let html = htmlString.replace(EMPTY_QUILL_PARAGRAPHS_REGEX, "");
if (typeof value === "string" && /<[^>]*>/g.test(value)) {
jsonObj[key] = processHtmlString(value); 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 jsonObj; return updated;
}; };
export const whichRepType = (props) => { export const whichRepType = (props) => {