diff --git a/.gitignore b/.gitignore
index 91dc1bbd..fdf5dd65 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,5 @@ pages/polling.js
/pages/api/endpoint/getaccounts_api.js
+
+
diff --git a/components/case/representation/index.js b/components/case/representation/index.js
index dcb9f4cf..41fdbb0e 100644
--- a/components/case/representation/index.js
+++ b/components/case/representation/index.js
@@ -367,6 +367,13 @@ let MakeRepresentation = (props) => {
todaysDate <= finalCommentsDate &&
buildArr.push("Local Impact Report");
+ isLPA &&
+ isDNS &&
+ currentView.caseReference.appealType != 846040019 &&
+ todaysDate >= startDate &&
+ todaysDate <= finalCommentsDate &&
+ buildArr.push("Statement");
+
!isDNS &&
currentView.caseReference.appealType != 846040004 &&
todaysDate >= startDate &&
@@ -772,10 +779,15 @@ let MakeRepresentation = (props) => {
props.props.currentView.caseReference.currentReference,
"pinswg_questionnaireduedate":
detailsObj.pinswg_questionnaireduedate,
- "pinswg_statementduedate": detailsObj.pinswg_statementduedate,
- "pinswg_statementsduedate": detailsObj.pinswg_statementsduedate,
+ "pinswg_statementduedate":
+ detailsObj.pinswg_statementduedate ||
+ detailsObj.pinswg_endofrepresentationperiod,
+ "pinswg_statementsduedate":
+ detailsObj.pinswg_statementsduedate ||
+ detailsObj.pinswg_endofrepresentationperiod,
"pinswg_finalcommentsduedate":
- detailsObj.pinswg_finalcommentsduedate,
+ detailsObj.pinswg_finalcommentsduedate ||
+ detailsObj.pinswg_endofrepresentationperiod,
"pinswg_name":
props.props.currentView.caseReference.currentReference,
"firstname": props.props.accountDetails.accountDetails.firstname,
diff --git a/components/case/representation/representationElements.js b/components/case/representation/representationElements.js
index 6057b18d..9fade1e2 100644
--- a/components/case/representation/representationElements.js
+++ b/components/case/representation/representationElements.js
@@ -944,8 +944,10 @@ export const RenderFileUpload = (field) => {
return "/assets/images/documenttypes/zip.png";
break;
case "image/jpeg":
+ return "/assets/images/documenttypes/jpg.png";
case "image/png":
- return URL.createObjectURL(fileObj);
+ return "/assets/images/documenttypes/jpg.png";
+ //return URL.createObjectURL(fileObj);
break;
default:
return "/assets/images/documenttypes/default.png";
@@ -1074,6 +1076,7 @@ export const RenderFileUpload = (field) => {
// Handle accepted files (clear error message when files are accepted)
const handleDropAccepted = () => {
+ setErrorMessage(null);
setRejectedFiles([]); // Clear any previously rejected file errorsss
};
@@ -1169,6 +1172,12 @@ export const RenderFileUpload = (field) => {
// Object.assign(values, {
// "fileList": buildAppealFilesArray,
// });
+ data.invalidFiles.length > 0 &&
+ (setRejectedFiles(data.invalidFiles),
+ setUploadCountMessage(
+ renamedAcceptedFiles.length -
+ data.invalidFiles.length
+ ));
getFilesFromBlobproxy(
field.containerID,
field.ticketnumber +
@@ -1215,32 +1224,16 @@ export const RenderFileUpload = (field) => {
)
-
- {uploadCountMessage > 0 &&
- completedUploadFiles == false && (
-
- {t("home:uploading-files-label", {
- number: uploadCountMessage,
- })}
-
- )}
- {completedUploadFiles > 0 &&
- uploadCountMessage > 0 && (
-
- {t(
- "home:completed-uploading-files-label",
- {
- number: uploadCountMessage,
- }
- )}
-
- )}
+ {/* */}
>
)}
- {rejectedFiles.length > 0 && (
-
+ {rejectedFiles.length > 0 && completedUploadFiles == true && (
+
{rejectedFiles.map((error, index) => (
- {error}
@@ -1248,6 +1241,20 @@ export const RenderFileUpload = (field) => {
)}
+ {uploadCountMessage > 0 && completedUploadFiles == false && (
+
+ {t("home:uploading-files-label", {
+ number: uploadCountMessage,
+ })}
+
+ )}
+ {completedUploadFiles > 0 && uploadCountMessage >= 0 && (
+
+ {t("home:completed-uploading-files-label", {
+ number: uploadCountMessage,
+ })}
+
+ )}
{field.meta.touched && field.meta.error && (
{field.meta.error}
)}
diff --git a/components/elements/index.js b/components/elements/index.js
index dfd8038d..f676b273 100644
--- a/components/elements/index.js
+++ b/components/elements/index.js
@@ -1851,8 +1851,10 @@ const RenderFileUpload = (field) => {
return "/assets/images/documenttypes/zip.png";
break;
case "image/jpeg":
+ return "/assets/images/documenttypes/jpg.png";
case "image/png":
- return URL.createObjectURL(fileObj);
+ return "/assets/images/documenttypes/png.png";
+ //return URL.createObjectURL(fileObj);
break;
default:
return "/assets/images/documenttypes/default.png";
@@ -2036,13 +2038,12 @@ const RenderFileUpload = (field) => {
);
field.input.onChange(renamedAcceptedFiles);
- setUploadCountMessage(renamedAcceptedFiles.length);
-
- console.log("werwerw");
field.setFileCount(
field.uploadCount + renamedAcceptedFiles.length
);
+ setUploadCountMessage(renamedAcceptedFiles.length);
+
uploadSingleFile(
renamedAcceptedFiles,
field.containerID,
@@ -2089,6 +2090,12 @@ const RenderFileUpload = (field) => {
Object.assign(values, {
"filesList": buildAppealFilesArray,
});
+ data.invalidFiles.length > 0 &&
+ (setRejectedFiles(data.invalidFiles),
+ setUploadCountMessage(
+ renamedAcceptedFiles.length -
+ data.invalidFiles.length
+ ));
getFilesFromBlobproxy(
field.containerID,
field.ticketnumber
@@ -2123,31 +2130,15 @@ const RenderFileUpload = (field) => {
{/* */}
- {uploadCountMessage > 0 &&
- completedUploadFiles == false && (
-
- {t("home:uploading-files-label", {
- number: uploadCountMessage,
- })}
-
- )}
- {completedUploadFiles > 0 &&
- uploadCountMessage > 0 && (
-
- {t(
- "home:completed-uploading-files-label",
- {
- number: uploadCountMessage,
- }
- )}
-
- )}
>
)}
- {rejectedFiles.length > 0 && (
-
+ {rejectedFiles.length > 0 && completedUploadFiles == true && (
+
{rejectedFiles.map((error, index) => (
- {error}
@@ -2155,6 +2146,20 @@ const RenderFileUpload = (field) => {
)}
+ {uploadCountMessage > 0 && completedUploadFiles == false && (
+
+ {t("home:uploading-files-label", {
+ number: uploadCountMessage,
+ })}
+
+ )}
+ {completedUploadFiles > 0 && uploadCountMessage >= 0 && (
+
+ {t("home:completed-uploading-files-label", {
+ number: uploadCountMessage,
+ })}
+
+ )}
{field.meta.touched && field.meta.error && (
{field.meta.error}
)}
diff --git a/components/mapping/index.js b/components/mapping/index.js
index c218594d..9cf76758 100644
--- a/components/mapping/index.js
+++ b/components/mapping/index.js
@@ -1,3 +1,4 @@
+import { he } from "date-fns/locale";
import GoogleMapReact from "google-map-react";
const GoogleMapComponent = (props) => {
const { center, zoom } = props;
@@ -21,22 +22,69 @@ const GoogleMapComponent = (props) => {
});
}
};
+
+ // console.log(
+ // "https://datamap.gov.wales/maps/pedw-dev/embed?center=" +
+ // props.center.lng +
+ // "," +
+ // props.center.lat +
+ // "&zoom=12#/"
+ // );
return (
-
ModelsMap(map, maps)}
- >
+ //
ModelsMap(map, maps)}
+ // >
+ <>
+ {" "}
+
+
+ >
);
};
diff --git a/components/search/advancedsearch.js b/components/search/advancedsearch.js
index 7fc0022c..1c23b9a1 100644
--- a/components/search/advancedsearch.js
+++ b/components/search/advancedsearch.js
@@ -580,10 +580,10 @@ let AdvancedSearch = (props) => {
label={t("search:appealtype-label")}
errormsg="Appeal type is required"
/>
- {props.props?.props.form[
- props.form
- ]?.values?.appealTypes.split(",")[0] ===
- "846040002" && (
+
+ {props.appealTypesValue?.split(
+ ","
+ )[0] === "846040002" && (
{
const selector = formValueSelector("advancedSearchForm"); // <-- same as form name
+AdvancedSearch = connect((state) => {
+ const appealTypesValue = selector(state, "appealTypes");
+
+ return {
+ appealTypesValue,
+ };
+})(AdvancedSearch);
+
export default connect(
mapStateToProps,
mapDispatchToProps
diff --git a/components/search/dnssearchresults.js b/components/search/dnssearchresults.js
index 2433cca5..29694ff9 100644
--- a/components/search/dnssearchresults.js
+++ b/components/search/dnssearchresults.js
@@ -753,12 +753,12 @@ const DNSSearchResults = (props) => {
{showMap == "true" && (
- {
onGoogleApiLoaded={({ map, maps }) =>
ModelsMap(map, maps)
}
- />
+ /> */}
+
+
)}
diff --git a/package.json b/package.json
index 3bc3b484..04575588 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"date-fns": "^2.30.0",
"dom": "^0.0.3",
"express": "^4.18.2",
+ "file-type": "^20.4.1",
"fs": "0.0.2",
"google-map-react": "^2.2.1",
"govuk-frontend": "^5.0.0",
diff --git a/pages/_document.js b/pages/_document.js
index 71b93947..b38fa74c 100644
--- a/pages/_document.js
+++ b/pages/_document.js
@@ -47,6 +47,7 @@ class MyDocument extends Document {
csp += `style-src 'self' 'unsafe-inline' https://pro.fontawesome.com/ https://www.google-analytics.com https://tagmanager.google.com/ https://www.googletagmanager.com/ https://fonts.googleapis.com/;`;
csp += `img-src 'self' 'unsafe-inline' https://maps.gstatic.com https://maps.googleapis.com https://www.gov.wales https://gov.wales https://fonts.gstatic.com https://www.googletagmanager.com https://www.google-analytics.com https://ssl.gstatic.com/ blob: data:;`;
csp += `font-src 'self' 'unsafe-inline' https://pro.fontawesome.com/ https://fonts.gstatic.com/ data:;`;
+ csp += `frame-src https://datamap.gov.wales`;
return (
diff --git a/pages/api/endpoint/getdnscoords_api.js b/pages/api/endpoint/getdnscoords_api.js
index 3bdc0b55..8b09582b 100644
--- a/pages/api/endpoint/getdnscoords_api.js
+++ b/pages/api/endpoint/getdnscoords_api.js
@@ -21,6 +21,70 @@ const hashAPIPath = (queryPath) => {
return (queryPath.indexOf("?") > -1 ? "&hash=" : "?hash=") + hashlink;
};
+const renameKeys = (obj) => {
+ const keyMappings = {
+ "pinswg_projectlocation": "location",
+ "pinswg_mapzoomlevel": "zoomLevel",
+ "pinswg_name": "projectName",
+ "pinswg_anticipatedgridreferenceeastingtext": "easting",
+ "pinswg_anticipatedgridreferencenorthingtext": "northing",
+ "pinswg_anticipatedgridrefeasting": "easting",
+ "pinswg_anticipatedgridrefnorthing": "northing",
+ "pinswg_projectname": "projectTitle",
+ "pinswg_dnsid": "dnsId",
+ "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue":
+ "lpaDisplayName",
+ "_pinswg_associatedlpa_value": "lpaId",
+ "_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue":
+ "appellantDisplayName",
+ "_pinswg_appellant_value": "appellantId",
+ "zoom": "mapZoom",
+ "center": "locationCenter",
+ };
+
+ let renamedObj = {};
+ Object.keys(obj).forEach((key) => {
+ // Skip keys that need to be removed
+ if (keysToRemove.includes(key)) {
+ return;
+ }
+
+ // Check if the key exists in the mapping
+ if (keyMappings[key]) {
+ renamedObj[keyMappings[key]] = obj[key];
+ } else {
+ renamedObj[key] = obj[key];
+ }
+ });
+
+ // Recursively rename keys in nested objects
+ if (obj.center) {
+ renamedObj.locationCenter = {
+ lat: obj.center.lat,
+ lng: obj.center.lng,
+ };
+ }
+
+ if (renamedObj.easting) {
+ renamedObj.easting = String(renamedObj.easting);
+ }
+ if (renamedObj.northing) {
+ renamedObj.northing = String(renamedObj.northing);
+ }
+
+ return renamedObj;
+};
+
+const keysToRemove = [
+ "_pinswg_associatedlpa_value@Microsoft.Dynamics.CRM.associatednavigationproperty",
+ "_pinswg_appellant_value@Microsoft.Dynamics.CRM.associatednavigationproperty",
+ "_pinswg_associatedlpa_value@Microsoft.Dynamics.CRM.lookuplogicalname",
+ "_pinswg_appellant_value@Microsoft.Dynamics.CRM.lookuplogicalname",
+ "pinswg_anticipatedgridrefeasting@OData.Community.Display.V1.FormattedValue",
+ "pinswg_anticipatedgridrefnorthing@OData.Community.Display.V1.FormattedValue",
+ // Add any other keys to remove here
+];
+
export default async function ApiProxy(req, res) {
var token = await getToken();
@@ -90,7 +154,15 @@ export default async function ApiProxy(req, res) {
});
// Send the merged values as the response
- return res.status(200).json(coordsObj);
+
+ const updatedData = {
+ value: coordsObj.value.map((item) => renameKeys(item)),
+ "@odata.count": coordsObj["@odata.count"],
+ };
+
+ return req.query.hasOwnProperty("fordmw")
+ ? res.status(200).json(updatedData)
+ : res.status(200).json(coordsObj);
} catch (error) {
// Catch any errors and send an error response
consoleLogger(error);
diff --git a/pages/api/file/uploadsinglefile.js b/pages/api/file/uploadsinglefile.js
index 382c0888..bc7af6e0 100644
--- a/pages/api/file/uploadsinglefile.js
+++ b/pages/api/file/uploadsinglefile.js
@@ -7,6 +7,9 @@ import {
import nextConnect from "next-connect";
import middleware from "../middleware/middleware";
import { consoleLogger } from "../../../actions";
+import { fileTypeFromBuffer } from "file-type";
+import fs from "fs";
+import path from "path";
const ApiProxy = nextConnect();
ApiProxy.use(middleware);
@@ -35,31 +38,99 @@ ApiProxy.post(async (req, res) => {
];
var allowedFilesFormData = {};
+ var invalidFiles = []; // To store the names of invalid files
+
+ // for (const [fileName, fileDetails] of Object.entries(req.files)) {
+ // if (allowedMimeTypes.includes(fileDetails[0].headers["content-type"])) {
+ // allowedFilesFormData[fileName] = fileDetails.map((file) => ({
+ // fieldName: file.fieldName,
+ // originalFilename: file.originalFilename,
+ // path: file.path,
+ // size: file.size,
+ // headers: file.headers,
+ // contentType: file.headers["content-type"],
+ // }));
+ // }
+ // }
for (const [fileName, fileDetails] of Object.entries(req.files)) {
- if (allowedMimeTypes.includes(fileDetails[0].headers["content-type"])) {
- allowedFilesFormData[fileName] = fileDetails.map((file) => ({
- fieldName: file.fieldName,
- originalFilename: file.originalFilename,
- path: file.path,
- size: file.size,
- headers: file.headers,
- contentType: file.headers["content-type"],
- }));
+ const file = fileDetails[0];
+ const filePath = file.path;
+
+ // Check the MIME type from file headers
+ const fileMimeType = file.headers["content-type"];
+ if (allowedMimeTypes.includes(fileMimeType)) {
+ // Check file signature (magic number) using file-type
+ const buffer = fs.readFileSync(filePath);
+
+ try {
+ const type = await fileTypeFromBuffer(buffer); // Correct usage of fileTypeFromBuffer
+ console.log("checking mime type ", type);
+ if (type && allowedMimeTypes.includes(type.mime)) {
+ // If the MIME type from the file signature matches the allowed list
+ allowedFilesFormData[fileName] = fileDetails.map(
+ (file) => ({
+ fieldName: file.fieldName,
+ originalFilename: file.originalFilename,
+ path: file.path,
+ size: file.size,
+ headers: file.headers,
+ contentType: fileMimeType,
+ })
+ );
+ } else {
+ console.log(
+ `\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\nFile ${fileName} has an invalid MIME type based on its content.\n\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\`
+ );
+ invalidFiles.push(fileName); // Track invalid file
+
+ // return res
+ // .status(400)
+ // .json({ error: `Invalid file type for ${fileName}` });
+ }
+ } catch (error) {
+ console.log(
+ `Error reading file ${fileName} for MIME type validation`,
+ error
+ );
+ // return res
+ // .status(500)
+ // .json({ error: "Failed to validate file type" });
+ }
+ } else {
+ console.log(
+ `\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\nFile ${fileName} has an unsupported MIME type: ${fileMimeType}\n\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\`
+ );
+ invalidFiles.push(fileName); // Track invalid file
+
+ // return res.status(400).json({
+ // error: `Unsupported MIME type for ${fileName}`,
+ // });
}
}
-
//console.log("allowedFilesFormData: ", allowedFilesFormData);
+ // If no valid files are found
+ // if (Object.keys(allowedFilesFormData).length === 0) {
+ // return res.status(400).json({
+ // error: "No valid files found",
+ // invalidFiles: invalidFiles, // Return the list of invalid files
+ // });
+ // }
+
+ invalidFiles = invalidFiles.map((fileName) => {
+ return `${fileName} - Invalid file`;
+ });
+
try {
const data = await uploadSingleFile(
allowedFilesFormData,
containerID,
casefolderID
).then((data) => {
- return res.status(200).json({ data });
+ return res.status(200).json({ data, invalidFiles });
});
- return res.status(200).json({ data });
+ return res.status(200).json({ data, invalidFiles });
} catch (error) {
consoleLogger(error);
return res.status(500).json({ error: "Failed to upload files" });
diff --git a/styles/sass/welshgov/_application.scss b/styles/sass/welshgov/_application.scss
index 87e36f36..02b49b02 100644
--- a/styles/sass/welshgov/_application.scss
+++ b/styles/sass/welshgov/_application.scss
@@ -1936,6 +1936,11 @@ ul#sharePageLinks.active {
position: absolute;
}
+
+.mappingFrame {
+ border: 1px solid $lightgrey
+}
+
//dns application view
.govuk-warning-text__icon {