Merged PR 1431: Sprint 1 - 14100 & 14115

Related work items: #14100, #14115
This commit is contained in:
Robert Bond
2025-02-20 07:36:53 +00:00
16 changed files with 499 additions and 103 deletions
+12
View File
@@ -301,6 +301,18 @@ export const getBasicDNSURLSearch = (searchString) => {
});
};
export const getSIPSEvents = (caseid) => {
return axios
.get(BASE_URL + "/api/endpoint/getsipsevents_api?caseid=" + caseid)
.then((res) => {
return res.data;
})
.catch((error) => {
consoleLogger(error);
return error.response;
});
};
export const getAddressSearchPaged = (
searchString,
pageNumber,
+1
View File
@@ -40,6 +40,7 @@ const Case = (props) => {
docsOffline={props.props.docsOffline}
documentDetailsObj={props.documentDetailsObj}
showFilteredDocs={props.showFilteredDocs}
eventsObj={props.eventsObj}
/>
{showRepresentations == true && (
<RepresentationList
+185
View File
@@ -0,0 +1,185 @@
import { setEventDetails } from "../../store/searchOutput/action";
import { setCurrentPage } from "../../store/currentView/action";
import { connect } from "react-redux";
import useTranslation from "next-translate/useTranslation";
import { formatDates } from "../utils";
const EventsDetails = (props) => {
let { t } = useTranslation();
const EventView = (eventsArr) => {
eventsArr = eventsArr.value;
return eventsArr.map((item, key) => {
<div>{item.pinswg_name}</div>;
});
};
const eventsArr = props.eventsObj?.value || [];
// event publishiing flag set to true displa
function hasOwnPropertyAndNotNull(obj, property) {
return obj.hasOwnProperty(property) && obj[property] !== null;
}
console.log(eventsArr.length > 0);
return (
eventsArr.length > 0 && (
<div className="govuk-grid-row">
<div className="card">
<div className="card-body">
<h2 className="govuk-heading-m ">Events</h2>
{eventsArr.map(
(item, key) =>
item.pinswg_eventpublishingflag ==
846040001 && (
<>
{" "}
<div className="eventContainer">
<div className="eventColumn">
<div>
<b>Name</b>:{" "}
{item.pinswg_name}
</div>
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventname"
) && (
<div>
<b>Event name</b>:{" "}
{item.pinswg_eventname}
</div>
)}
</div>
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddressline1"
) && (
<div>
{
item.pinswg_eventaddressline1
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddressline2"
) && (
<div>
{
item.pinswg_eventaddressline2
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresstown"
) && (
<div>
{
item.pinswg_eventaddresstown
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresscounty"
) && (
<div>
{
item.pinswg_eventaddresscounty
}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_eventaddresscounty"
) && (
<div>
{
item.pinswg_eventaddresspostcode
}
</div>
)}
</div>
{/* type of event
start date date of event - end date of event
if virtual event no address showNoOfRecords
show event address */}
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
"pinswg_dateeventrequested"
) && (
<div>
<b>Start Date</b>:{" "}
{formatDates(
item.pinswg_dateeventrequested
)}
</div>
)}
{hasOwnPropertyAndNotNull(
item,
"pinswg_enddateoftheevent"
) && (
<div>
<b>End Date</b>:{" "}
{item.pinswg_enddateoftheevent !=
null &&
formatDates(
item.pinswg_enddateoftheevent
)}
</div>
)}
</div>
<div className="eventColumn">
{hasOwnPropertyAndNotNull(
item,
[
"pinswg_typeofevent@OData.Community.Display.V1.FormattedValue",
]
) && (
<div>
<b>Type of event</b>:{" "}
{
item[
"pinswg_typeofevent@OData.Community.Display.V1.FormattedValue"
]
}
</div>
)}
</div>
</div>
</>
)
)}{" "}
</div>
</div>
</div>
)
);
};
const mapStateToProps = (state) => {
return {
...state,
};
};
const mapDispatchToProps = (dispatch) => {
return {
setEventDetails: (eventsObj) => {
dispatch(setEventDetails(eventsObj));
},
setCurrentPage: (currentPage) => {
dispatch(setCurrentPage(currentPage));
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(EventsDetails);
-1
View File
@@ -1192,7 +1192,6 @@ let MakeRepresentation = (props) => {
</h1>
<div id="rep-form">
<div className="govuk-grid-column-three-quarters wgForm">
www
{whichControl()}
</div>
+3
View File
@@ -7,6 +7,7 @@ import { useEffect, useState } from "react";
import { connect } from "react-redux";
import transLookup from "../../data/lookuptranslations.json";
import Documents from "./documents";
import EventsDetails from "./events";
import {
createWatchedCases,
@@ -768,6 +769,8 @@ const CaseSummary = (props) => {
)}
{showSummary(casesObj, detailsObj)}
<EventsDetails eventsObj={props.eventsObj} />
<Documents
incidentid={props.incidentid}
caseReference={props.caseReference}
+1 -1
View File
@@ -39,7 +39,7 @@
"inspectorate-card-visit-link": "Hafan",
"inspectorate-card-alt-text": "Yr Arolygiaeth Gynllunio",
"dns-card-title": "Gweld yr holl Brosiectau Seilwaith",
"dns-card-paragraph": "Gellir dosbarthu prosiectau o bwysigrwydd cenedlaethol fel Datblygiad o Arwyddocâd Cenedlaethol neu dan ddeddfwriaeth newydd, Prosiect Seilwaith Arwyddocaol.",
"dns-card-paragraph": "Mae Prosiect Seilwaith yn fath o gais cynllunio syn arwyddocaol yn genedlaethol.",
"dns-card-button": "Gweld pob cais",
"logging-in-heading": "Rydym yn dilysu eich cyfrif. Arhoswch a pheidiwch ag adnewyddu'r dudalen",
"logging-in-paragraph": "Arhoswch os gwelwch yn dda...",
+1 -1
View File
@@ -39,7 +39,7 @@
"inspectorate-card-visit-link": "Home",
"inspectorate-card-alt-text": "The Planning Inspectorate",
"dns-card-title": "View all Infrastructure Projects",
"dns-card-paragraph": "Projects of national importance can be classed as a Development of National Significance or under new legislation, a Significant Infrastructure Project.",
"dns-card-paragraph": "An Infrastructure Project is a type of planning application that is nationally significant.",
"dns-card-button": "View all applications",
"logging-in-heading": "We are authenticating your account please wait and don't refresh",
"logging-in-paragraph": "Please wait...",
+44
View File
@@ -0,0 +1,44 @@
import axios from "axios";
import CryptoJS from "crypto-js";
import { azureHeaders, consoleLogger, getToken } from "../../../actions";
const WORDKEY = process.env.HASHKEY;
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
const hashAPIPath = (queryPath) => {
var hashlink = CryptoJS.HmacSHA256(
queryPath,
CryptoJS.enc.Hex.parse(WORDKEY)
);
hashlink = hashlink.toString(CryptoJS.enc.Hex);
//return "&hash=" + hashlink;
return (queryPath.indexOf("?") > -1 ? "&hash=" : "?hash=") + hashlink;
};
export default async function ApiProxy(req, res) {
var caseid = req.query.caseid;
var token = await getToken();
var queryUrl =
"pinswg_sipsevents?$filter=_pinswg_sipseventsid_value eq " +
caseid +
"&$count=true";
return axios
.get(
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
});
}
+14 -1
View File
@@ -9,6 +9,7 @@ import {
getIP,
getPersonalAccount,
getPortalLogin,
getSIPSEvents,
} from "../../actions";
import Breadcrumbs from "../../components/breadcrumbs";
import Case from "../../components/case";
@@ -20,6 +21,7 @@ import { setAccountDetails } from "../../store/accountDetails/action";
import { setCurrentReference } from "../../store/currentView/action";
import { setSearch } from "../../store/search/action";
import {
setEventDetails,
setSearchDetails,
setSearchResults,
} from "../../store/searchOutput/action";
@@ -99,6 +101,7 @@ const CaseHome = (props) => {
messagesObj={props.messagesObj}
showFilteredDocs={props.showFilteredDocs}
showMaps={props.showMaps}
eventsObj={props.searchResultsObj.eventsObj}
/>
</div>
<Footer
@@ -148,6 +151,15 @@ export const getServerSideProps = wrapper.getServerSideProps(
const searchResultsObj = await getBasicSearch(developmentQuery);
const searchDetailsObj = await getSearchDetails(searchResultsObj);
var eventsObj = {};
if (searchResultsObj.value[0].pinswg_appealcasetype == 846040002) {
eventsObj = await getSIPSEvents(
searchDetailsObj[0].value[0].pinswg_sipsid
);
store.dispatch(setEventDetails(eventsObj));
}
//console.log(
// "\n======================================\n",
// searchResultsObj,
@@ -214,6 +226,7 @@ export const getServerSideProps = wrapper.getServerSideProps(
searchResultsObj: {
searchResultsObj: searchResultsObj,
searchDetailsObj: searchDetailsObj,
eventsObj: eventsObj,
},
currentType: "directResultsObj",
docsOffline: process.env.DOCAPI_OFFLINE || false,
@@ -232,7 +245,7 @@ const mapStateToProps = (state) => {
accountDetails: state.accountDetails,
currentView: state.currentView,
search: state.search,
searchResultsObj: state.searchResultsObj,
//searchResultsObj: state.searchResultsObj,
documentDetailsObj: state.searchResultsObj.documentDetailsObj,
formData: state.formData,
appealType: state.appealType,
+13
View File
@@ -9,6 +9,7 @@ import {
getIP,
getPersonalAccount,
getPortalLogin,
getSIPSEvents,
} from "../../actions";
import Breadcrumbs from "../../components/breadcrumbs";
import Case from "../../components/case";
@@ -20,6 +21,7 @@ import { setAccountDetails } from "../../store/accountDetails/action";
import { setCurrentReference } from "../../store/currentView/action";
import { setSearch } from "../../store/search/action";
import {
setEventDetails,
setSearchDetails,
setSearchResults,
} from "../../store/searchOutput/action";
@@ -98,6 +100,7 @@ const CaseHome = (props) => {
messagesObj={props.messagesObj}
showFilteredDocs={props.showFilteredDocs}
showMaps={props.showMaps}
eventsObj={props.searchResultsObj.eventsObj}
/>
</div>
<Footer
@@ -148,6 +151,15 @@ export const getServerSideProps = wrapper.getServerSideProps(
const searchResultsObj = await getBasicDNSURLSearch(developmentQuery);
const searchDetailsObj = await getSearchDetails(searchResultsObj);
var eventsObj = {};
if (searchResultsObj.value[0].pinswg_appealcasetype == 846040002)
eventsObj = await getSIPSEvents(
searchDetailsObj[0].value[0].pinswg_sipsid
);
store.dispatch(setEventDetails(eventsObj));
// console.log("eventsObj:", eventsObj);
// console.log(
// "\n======================================\n",
// searchResultsObj,
@@ -225,6 +237,7 @@ export const getServerSideProps = wrapper.getServerSideProps(
searchResultsObj: {
searchResultsObj: searchResultsObj,
searchDetailsObj: searchDetailsObj,
eventsObj: eventsObj,
},
currentType: "directResultsObj",
docsOffline: process.env.DOCAPI_OFFLINE || false,
+13 -1
View File
@@ -12,6 +12,7 @@ import {
getPortalLogin,
getPortalModuleDetails,
getWatchedCases,
getSIPSEvents,
} from "../../../actions";
import { getFormCollectionByID } from "../../../components/utils";
@@ -40,6 +41,7 @@ import { setSearch } from "../../../store/search/action";
import {
setSearchDetails,
setSearchResults,
setEventDetails,
} from "../../../store/searchOutput/action";
import { wrapper } from "../../../store/store";
import {
@@ -116,6 +118,7 @@ const CaseHome = (props) => {
messagesObj={props.messagesObj}
showFilteredDocs={props.showFilteredDocs}
showMaps={props.showMaps}
eventsObj={props.searchResultsObj.eventsObj}
/>
</div>
<Footer
@@ -182,6 +185,14 @@ export const getServerSideProps = wrapper.getServerSideProps(
const searchResultsObj = await getBasicSearch(developmentQuery);
const searchDetailsObj = await getSearchDetails(searchResultsObj);
var eventsObj = {};
if (searchResultsObj.value[0].pinswg_appealcasetype == 846040002) {
eventsObj = await getSIPSEvents(
searchDetailsObj[0].value[0].pinswg_sipsid
);
store.dispatch(setEventDetails(eventsObj));
}
//console.log(
// "\n======================================\n",
// searchResultsObj,
@@ -354,6 +365,7 @@ export const getServerSideProps = wrapper.getServerSideProps(
searchResultsObj: {
searchResultsObj: searchResultsObj,
searchDetailsObj: searchDetailsObj,
eventsObj: eventsObj,
},
currentType: "directResultsObj",
docsOffline: process.env.DOCAPI_OFFLINE || false,
@@ -458,7 +470,7 @@ const mapStateToProps = (state) => {
accountDetails: state.accountDetails,
currentView: state.currentView,
search: state.search,
searchResultsObj: state.searchResultsObj,
//searchResultsObj: state.searchResultsObj,
documentDetailsObj: state.searchResultsObj.documentDetailsObj,
formData: state.formData,
appealType: state.appealType,
+12
View File
@@ -9,6 +9,7 @@ import {
getIP,
getPersonalAccount,
getPortalLogin,
getSIPSEvents,
} from "../../../actions";
import Breadcrumbs from "../../../components/breadcrumbs";
import Case from "../../../components/case";
@@ -20,6 +21,7 @@ import { setAccountDetails } from "../../../store/accountDetails/action";
import { setCurrentReference } from "../../../store/currentView/action";
import { setSearch } from "../../../store/search/action";
import {
setEventDetails,
setSearchDetails,
setSearchResults,
} from "../../../store/searchOutput/action";
@@ -98,6 +100,7 @@ const CaseHome = (props) => {
messagesObj={props.messagesObj}
showFilteredDocs={props.showFilteredDocs}
showMaps={props.showMaps}
eventsObj={props.searchResultsObj.eventsObj}
/>
</div>
<Footer
@@ -148,6 +151,14 @@ export const getServerSideProps = wrapper.getServerSideProps(
const searchResultsObj = await getBasicDNSURLSearch(developmentQuery);
const searchDetailsObj = await getSearchDetails(searchResultsObj);
var eventsObj = {};
if (searchResultsObj.value[0].pinswg_appealcasetype == 846040002)
eventsObj = await getSIPSEvents(
searchDetailsObj[0].value[0].pinswg_sipsid
);
store.dispatch(setEventDetails(eventsObj));
// console.log(
// "\n======================================\n",
// searchResultsObj,
@@ -225,6 +236,7 @@ export const getServerSideProps = wrapper.getServerSideProps(
searchResultsObj: {
searchResultsObj: searchResultsObj,
searchDetailsObj: searchDetailsObj,
eventsObj: eventsObj,
},
currentType: "directResultsObj",
docsOffline: process.env.DOCAPI_OFFLINE || false,
+162 -98
View File
@@ -373,115 +373,179 @@ export const getServerSideProps = wrapper.getServerSideProps(
}
);
// const getDetails = async (resultsObj, detailsType) => {
// let detailsArr = [];
// const limitRequests = pLimit(1); // Limit to 5 concurrent requests
// resultsObj =
// detailsType == "mySubmittedReps" ? resultsObj : resultsObj.value;
// if (detailsType == "myRepresentations") {
// limitRequests(async () => {
// resultsObj.map((searchDetail, index) => {
// detailsArr.push(
// getCase(searchDetail["incidentID"])
// .then(async (data) => {
// let caseID = "";
// switch (detailsType) {
// case "myCases":
// caseID = data.pinswg_title;
// break;
// case "myWatchedCases":
// case "mySubmittedReps":
// caseID =
// data[
// "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
// ];
// break;
// case "awaitingSubmission":
// case "myRepresentations":
// try {
// caseID = data.ticketnumber;
// } catch {
// console.log("missing:", data);
// }
// break;
// default:
// caseID = data.pinswg_title;
// }
// return await getPortalModuleDetails(
// getFormCollectionByID(
// data.pinswg_appealcasetype
// ).LogicalCollectionName,
// caseID
// ).catch((error) => {
// console.log(
// "=============================\ngetPortalModuleDetails error",
// error
// );
// });
// })
// .catch((error) => {
// console.log(
// "=============================\ngetCase error",
// error
// );
// })
// );
// });
// });
// }
// //debugger;
// await Promise.all(
// resultsObj.map(async (searchDetail, index) => {
// limitRequests(async () => {
// try {
// let caseID = "";
// switch (detailsType) {
// case "myCases":
// caseID = searchDetail.pinswg_title;
// break;
// case "myWatchedCases":
// case "mySubmittedReps":
// caseID =
// searchDetail[
// "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
// ];
// break;
// case "awaitingSubmission":
// caseID = searchDetail.ticketnumber;
// break;
// case "myRepresentations":
// caseID = searchDetail.casereference;
// break;
// default:
// caseID = searchDetail.pinswg_title;
// }
// console.log(detailsType, " case id : ", caseID);
// searchDetail.pinswg_appealcasetype != null &&
// detailsArr.push(
// getPortalModuleDetails(
// getFormCollectionByID(
// searchDetail.pinswg_appealcasetype
// ).LogicalCollectionName,
// caseID
// )
// );
// } catch (error) {
// console.log("Error processing case:", error);
// }
// });
// })
// );
// let detArr = Promise.all(detailsArr);
// // console.log(detArr);
// return detArr;
// };
const getDetails = async (resultsObj, detailsType) => {
let detailsArr = [];
const limitRequests = pLimit(5); // Limit to 5 concurrent requests
const limitRequests = pLimit(5); // Allow up to 5 concurrent requests
// Adjust resultsObj based on detailsType
resultsObj =
detailsType == "mySubmittedReps" ? resultsObj : resultsObj.value;
detailsType === "mySubmittedReps" ? resultsObj : resultsObj.value;
if (detailsType == "myRepresentations") {
limitRequests(async () => {
resultsObj.map((searchDetail, index) => {
detailsArr.push(
getCase(searchDetail["incidentID"])
.then(async (data) => {
let caseID = "";
const getDetailsForCase = async (searchDetail) => {
try {
let caseID = "";
switch (detailsType) {
case "myCases":
caseID = data.pinswg_title;
break;
case "myWatchedCases":
case "mySubmittedReps":
caseID =
data[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
];
break;
case "awaitingSubmission":
case "myRepresentations":
try {
caseID = data.ticketnumber;
} catch {
console.log("missing:", data);
}
// Determine the case ID based on the detailsType
switch (detailsType) {
case "myCases":
caseID = searchDetail.pinswg_title;
break;
case "myWatchedCases":
case "mySubmittedReps":
caseID =
searchDetail[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
];
break;
case "awaitingSubmission":
caseID = searchDetail.ticketnumber;
break;
case "myRepresentations":
caseID = searchDetail.casereference;
break;
default:
caseID = searchDetail.pinswg_title;
}
break;
default:
caseID = data.pinswg_title;
}
return await getPortalModuleDetails(
getFormCollectionByID(
data.pinswg_appealcasetype
).LogicalCollectionName,
caseID
).catch((error) => {
console.log(
"=============================\ngetPortalModuleDetails error",
error
);
});
})
.catch((error) => {
console.log(
"=============================\ngetCase error",
error
);
})
console.log(detailsType, " case id: ", caseID);
// If the appeal case type is valid, fetch the portal module details
if (searchDetail.pinswg_appealcasetype != null) {
const formCollectionName = getFormCollectionByID(
searchDetail.pinswg_appealcasetype
).LogicalCollectionName;
const details = await getPortalModuleDetails(
formCollectionName,
caseID
);
});
});
}
//debugger;
await Promise.all(
resultsObj.map(async (searchDetail, index) => {
limitRequests(async () => {
try {
let caseID = "";
detailsArr.push(details);
}
} catch (error) {
console.log("Error processing case:", error);
}
};
switch (detailsType) {
case "myCases":
caseID = searchDetail.pinswg_title;
break;
case "myWatchedCases":
case "mySubmittedReps":
caseID =
searchDetail[
"_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue"
];
break;
case "awaitingSubmission":
caseID = searchDetail.ticketnumber;
break;
case "myRepresentations":
caseID = searchDetail.casereference;
break;
default:
caseID = searchDetail.pinswg_title;
}
// Use limitRequests to manage concurrency
const promises = resultsObj.map((searchDetail) => {
return limitRequests(() => getDetailsForCase(searchDetail));
});
console.log(detailsType, " case id : ", caseID);
// Wait for all the requests to complete
await Promise.all(promises);
searchDetail.pinswg_appealcasetype != null &&
detailsArr.push(
getPortalModuleDetails(
getFormCollectionByID(
searchDetail.pinswg_appealcasetype
).LogicalCollectionName,
caseID
)
);
} catch (error) {
console.log("Error processing case:", error);
}
});
})
);
let detArr = Promise.all(detailsArr);
// console.log(detArr);
return detArr;
return detailsArr;
};
const mapStateToProps = (state) => {
+8
View File
@@ -7,6 +7,7 @@ export const searchResultsActionTypes = {
SETDOCUMENTHISTORY: "SETDOCUMENTHISTORY",
SETREPRESENTATIONS: "SETREPRESENTATIONS",
SETDNSCOORDS: "SETDNSCOORDS",
SETEVENTDETAILS: "SETEVENTDETAILS",
};
export const getSearchResultshObj = () => (dispatch) => {
@@ -55,3 +56,10 @@ export const setDNSCoords = (dnsCoords) => (dispatch) => {
dnsCoordsObj: dnsCoords,
});
};
export const setEventDetails = (eventsDetails) => (dispatch) => {
return dispatch({
type: searchResultsActionTypes.SETEVENTDETAILS,
eventDetailsObj: eventsDetails,
});
};
+6
View File
@@ -6,6 +6,7 @@ const searchResultsInitialState = {
documentDetailsObj: {},
representationsObj: {},
dnsCoordsObj: {},
eventDetailsObj: {},
};
export default function reducer(state = searchResultsInitialState, action) {
@@ -36,6 +37,11 @@ export default function reducer(state = searchResultsInitialState, action) {
...state,
dnsCoordsObj: action.dnsCoordsObj,
};
case searchResultsActionTypes.SETEVENTDETAILS:
return {
...state,
eventDetailsObj: action.eventDetailsObj,
};
default:
return state;
}
+24
View File
@@ -2932,4 +2932,28 @@ ul.subFieldList {
.ql-snow .ql-tooltip {
z-index: 1000;
}
.eventContainer {
display: flex;
margin-bottom: 20px;
border-bottom: 1px solid $lightgrey_semi;
padding-bottom: 10px;
@media screen and (max-width: 768px) {
display: block;
padding-bottom: 10px;
}
.eventColumn {
line-height: 1.5;
width: 25%;
@media screen and (max-width: 768px) {
width: 100%;
}
}
}