Merged PR 1394: PII-UAT 270125
This commit is contained in:
@@ -865,6 +865,7 @@ let MakeRepresentation = (props) => {
|
|||||||
? (Object.assign(values, {
|
? (Object.assign(values, {
|
||||||
"filesList": props.currentView.fileList,
|
"filesList": props.currentView.fileList,
|
||||||
}),
|
}),
|
||||||
|
(values = updateLinks(values)),
|
||||||
uploadRepresentationFiles(values),
|
uploadRepresentationFiles(values),
|
||||||
router.replace(
|
router.replace(
|
||||||
router.locale != "en"
|
router.locale != "en"
|
||||||
@@ -875,6 +876,7 @@ let MakeRepresentation = (props) => {
|
|||||||
"filesList": props.currentView.fileList,
|
"filesList": props.currentView.fileList,
|
||||||
}),
|
}),
|
||||||
console.log("Rep Updated - ", props.caseReference),
|
console.log("Rep Updated - ", props.caseReference),
|
||||||
|
(values = updateLinks(values)),
|
||||||
uploadRepresentationFiles(values);
|
uploadRepresentationFiles(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1046,7 +1048,8 @@ let MakeRepresentation = (props) => {
|
|||||||
).then((data) => {
|
).then((data) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
data.status == "success" &&
|
data.status == "success" &&
|
||||||
(uploadRepresentationFiles(values),
|
((values = updateLinks(values)),
|
||||||
|
uploadRepresentationFiles(values),
|
||||||
setRepresentationSubmit(true),
|
setRepresentationSubmit(true),
|
||||||
setRepresentationSubmitConfirmation(true));
|
setRepresentationSubmitConfirmation(true));
|
||||||
});
|
});
|
||||||
@@ -1100,8 +1103,6 @@ let MakeRepresentation = (props) => {
|
|||||||
? cleanFilesList(values)
|
? cleanFilesList(values)
|
||||||
: values;
|
: values;
|
||||||
|
|
||||||
values = updateLinks(values);
|
|
||||||
|
|
||||||
// get filelists from values object
|
// get filelists from values object
|
||||||
let fileListObj = _.filter(values, function (v, key) {
|
let fileListObj = _.filter(values, function (v, key) {
|
||||||
return _.includes(key, "representationDocuments");
|
return _.includes(key, "representationDocuments");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import useTranslation from "next-translate/useTranslation";
|
|||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import router from "next/router";
|
import router from "next/router";
|
||||||
import React, { useMemo, useState } from "react";
|
import React, { useMemo, useState, useRef } from "react";
|
||||||
import DatePicker from "react-datepicker";
|
import DatePicker from "react-datepicker";
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import Dropzone from "react-dropzone";
|
import Dropzone from "react-dropzone";
|
||||||
@@ -726,7 +726,7 @@ export const RenderMultiline = ({
|
|||||||
toolbar: [
|
toolbar: [
|
||||||
[{ "header": [1, 2, false] }],
|
[{ "header": [1, 2, false] }],
|
||||||
["bold", "italic", "underline", "blockquote"],
|
["bold", "italic", "underline", "blockquote"],
|
||||||
[{ "list": "ordered" }, { "list": "bullet" }, "link"],
|
[{ "list": "ordered" }, { "list": "bullet" }],
|
||||||
["clean"],
|
["clean"],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
+12
-5
@@ -889,9 +889,10 @@ let Enforcement_Questionnaire = (props) => {
|
|||||||
)}
|
)}
|
||||||
component={RenderLPACondtionalRadioList}
|
component={RenderLPACondtionalRadioList}
|
||||||
validate={[required]}
|
validate={[required]}
|
||||||
legend={t(
|
legend={
|
||||||
"myrepresentations:enf-section-question-31a"
|
"a) " +
|
||||||
)}
|
t("myrepresentations:enf-section-question-31a")
|
||||||
|
}
|
||||||
conditionalLabel={t(
|
conditionalLabel={t(
|
||||||
"myrepresentations:enf-section-question-31a-hint"
|
"myrepresentations:enf-section-question-31a-hint"
|
||||||
)}
|
)}
|
||||||
@@ -901,7 +902,10 @@ let Enforcement_Questionnaire = (props) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Field
|
<Field
|
||||||
label={t("myrepresentations:enf-section-question-31b")}
|
label={
|
||||||
|
"b) " +
|
||||||
|
t("myrepresentations:enf-section-question-31b")
|
||||||
|
}
|
||||||
name="developmentNotTakePlaceBiodiversity"
|
name="developmentNotTakePlaceBiodiversity"
|
||||||
id="developmentNotTakePlaceBiodiversity"
|
id="developmentNotTakePlaceBiodiversity"
|
||||||
component={RenderRadioList}
|
component={RenderRadioList}
|
||||||
@@ -915,7 +919,10 @@ let Enforcement_Questionnaire = (props) => {
|
|||||||
aria-describedby={props.name + "-hint"}
|
aria-describedby={props.name + "-hint"}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
label={t("myrepresentations:enf-section-question-31c")}
|
label={
|
||||||
|
"c) " +
|
||||||
|
t("myrepresentations:enf-section-question-31c")
|
||||||
|
}
|
||||||
name="developmentNotTakePlaceBroadband"
|
name="developmentNotTakePlaceBroadband"
|
||||||
id="developmentNotTakePlaceBroadband"
|
id="developmentNotTakePlaceBroadband"
|
||||||
component={RenderRadioList}
|
component={RenderRadioList}
|
||||||
|
|||||||
+59
-53
@@ -551,66 +551,72 @@ export const getDocumentTypeFromFilename = (filename) => {
|
|||||||
return doctypeCode;
|
return doctypeCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateLinks = (jsonObject) => {
|
export const updateLinks = (jsonObj) => {
|
||||||
const wrapPlainUrlsInAnchorTags = (htmlString) => {
|
const parser = new DOMParser();
|
||||||
return htmlString
|
|
||||||
.replace(
|
// Function to process the HTML string and replace URLs with <a> tags
|
||||||
/(?<=^|>|\s)(?=\S)(?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:\/[^\s]*)?(?=\s|<|$)/g,
|
const processHtmlString = (htmlString) => {
|
||||||
(match) => {
|
const doc = parser.parseFromString(htmlString, "text/html");
|
||||||
// If the match is already wrapped in <a> tag, return it as is
|
|
||||||
if (match.includes('<a href="') || match.includes("<a ")) {
|
// Find all text nodes in the document
|
||||||
return match;
|
const walk = (node) => {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
// Check if the text node contains a URL (simple check for a URL pattern)
|
||||||
|
const urlRegex =
|
||||||
|
/(?:https?:\/\/)?(?:www\.)?([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})(\/[^\s]*)?/g;
|
||||||
|
let match;
|
||||||
|
|
||||||
|
// Process the text node if it contains a URL
|
||||||
|
while ((match = urlRegex.exec(node.textContent)) !== null) {
|
||||||
|
// Construct the full URL by adding the protocol if missing, and the domain and path
|
||||||
|
let fullUrl = match[0];
|
||||||
|
if (
|
||||||
|
!fullUrl.startsWith("http://") &&
|
||||||
|
!fullUrl.startsWith("https://")
|
||||||
|
) {
|
||||||
|
fullUrl = `https://${match[1]}${match[2] || ""}`; // Default to https
|
||||||
}
|
}
|
||||||
// Check if the URL starts with http:// or https://, else prepend http://
|
|
||||||
const url =
|
|
||||||
match.startsWith("http://") ||
|
|
||||||
match.startsWith("https://")
|
|
||||||
? match
|
|
||||||
: "https://" + match;
|
|
||||||
|
|
||||||
// Return the URL wrapped in <a> tag
|
// Check if the match is already inside an <a> tag, if so, skip it
|
||||||
return `<a href="${url}" rel="noopener noreferrer" target="_blank">${match}</a>`;
|
if (node.parentNode.tagName !== "A") {
|
||||||
|
const anchor = document.createElement("a");
|
||||||
|
anchor.href = fullUrl;
|
||||||
|
anchor.textContent = match[0];
|
||||||
|
|
||||||
|
// Add rel="noopener noreferrer" for security
|
||||||
|
anchor.setAttribute("rel", "noopener noreferrer");
|
||||||
|
|
||||||
|
// Replace the URL with the anchor element in the text node
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(node);
|
||||||
|
range.deleteContents();
|
||||||
|
range.insertNode(anchor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
/<a [^>]*><a [^>]*>(.*?)<\/a><\/a>/g,
|
|
||||||
(match, innerContent) => {
|
|
||||||
return `<a href="${innerContent}" rel="noopener noreferrer" target="_blank">${innerContent}</a>`;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
// Helper function to ensure that any href attributes in <a> tags have https/http
|
|
||||||
const ensureHttpsInLinks = (inputString) => {
|
|
||||||
// Match <a> tags with href attributes and check if they lack a scheme (http:// or https://)
|
|
||||||
return inputString.replace(
|
|
||||||
/<a [^>]*href=["']([^"']*)["'][^>]*>/g,
|
|
||||||
(match, url) => {
|
|
||||||
// If the URL doesn't already have a scheme (http:// or https://), add https://
|
|
||||||
if (!/^https?:\/\//.test(url)) {
|
|
||||||
const newUrl = `https://${url}`;
|
|
||||||
return match.replace(url, newUrl);
|
|
||||||
}
|
|
||||||
return match; // Return the unchanged anchor tag if it already has a scheme
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Traverse child nodes
|
||||||
|
for (let i = 0; i < node.childNodes.length; i++) {
|
||||||
|
walk(node.childNodes[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
walk(doc.body);
|
||||||
|
|
||||||
|
return doc.body.innerHTML;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Iterate through all properties of the JSON object
|
// Iterate over the JSON object and process values that are strings (HTML content)
|
||||||
Object.keys(jsonObject).forEach((key) => {
|
for (const key in jsonObj) {
|
||||||
const value = jsonObject[key];
|
if (jsonObj.hasOwnProperty(key)) {
|
||||||
|
const value = jsonObj[key];
|
||||||
|
|
||||||
// If the value is a string and contains plain URLs that are not wrapped
|
// If the value is a string and contains HTML, process it
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string" && /<[^>]*>/g.test(value)) {
|
||||||
// Step 1: Wrap plain URLs in anchor tags if not already wrapped
|
jsonObj[key] = processHtmlString(value);
|
||||||
let updatedValue = wrapPlainUrlsInAnchorTags(value);
|
}
|
||||||
|
|
||||||
// Step 2: Ensure that hrefs in anchor tags have https:// or http://
|
|
||||||
updatedValue = ensureHttpsInLinks(updatedValue);
|
|
||||||
|
|
||||||
// Assign the updated value back to the key
|
|
||||||
jsonObject[key] = updatedValue;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return jsonObject;
|
return jsonObj;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-pdf": "^7.6.0",
|
"react-pdf": "^7.6.0",
|
||||||
"react-pdf-html": "^1.1.18",
|
"react-pdf-html": "^1.1.18",
|
||||||
|
"react-quill": "^2.0.0",
|
||||||
"react-quill-new": "^3.3.3",
|
"react-quill-new": "^3.3.3",
|
||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.6",
|
||||||
"redux": "^4.2.1",
|
"redux": "^4.2.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user