diff --git a/.env.local b/.env.local index fb79879b..b4bd9db4 100644 --- a/.env.local +++ b/.env.local @@ -13,31 +13,31 @@ HASHKEY = 028ffbae928d7191c0017f298260995f901d78eabde1436c0af0423459cc3715832136 # CRMURL = "devcrm2016.llcdt.gov.wales/DVPINS" # //New Dev oauth ESNR -# CLIENT_ID = 9b834097-03d7-409b-b038-ecfec31a394a -# CLIENT_SECRET = .Jf8Q~tKMObCJjhh_hy3J5AIctFrBalU4FS~tdxk -# RELAY_ROOT = https://ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net/ar-hc-lz-pedw-dev-uks-01/ -# RELAYURI = "ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net" -# RELAYPATH = "ar-hc-lz-pedw-dev-uks-01" -# CRMURL = "devcrm2016.llcdt.gov.wales/DVPINS" +CLIENT_ID = 9b834097-03d7-409b-b038-ecfec31a394a +CLIENT_SECRET = .Jf8Q~tKMObCJjhh_hy3J5AIctFrBalU4FS~tdxk +RELAY_ROOT = https://ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net/ar-hc-lz-pedw-dev-uks-01/ +RELAYURI = "ar-ns-lz-pedw-dev-uks-01.servicebus.windows.net" +RELAYPATH = "ar-hc-lz-pedw-dev-uks-01" +CRMURL = "devcrm2016.llcdt.gov.wales/DVPINS" # //New Test -# CLIENT_ID = d40b9373-96c2-4b04-8bd8-c2a2fe6444c1 -# CLIENT_SECRET = 6hT8Q~glL~jloWpGmvXw3UY37QFwjUE0r._jobEM -# RELAY_ROOT = https://ar-ns-lz-pedw-test-uks-01.servicebus.windows.net/ar-hc-lz-pedw-test-uks-01/ -# RELAYURI = "ar-ns-lz-pedw-test-uks-01.servicebus.windows.net" -# RELAYPATH = "ar-hc-lz-pedw-test-uks-01" -# CRMURL = "tscrm2016.llcdt.gov.wales/UATPINS" +CLIENT_ID = d40b9373-96c2-4b04-8bd8-c2a2fe6444c1 +CLIENT_SECRET = 6hT8Q~glL~jloWpGmvXw3UY37QFwjUE0r._jobEM +RELAY_ROOT = https://ar-ns-lz-pedw-test-uks-01.servicebus.windows.net/ar-hc-lz-pedw-test-uks-01/ +RELAYURI = "ar-ns-lz-pedw-test-uks-01.servicebus.windows.net" +RELAYPATH = "ar-hc-lz-pedw-test-uks-01" +CRMURL = "tscrm2016.llcdt.gov.wales/UATPINS" -# //New PreProd -CLIENT_ID = ab6c4678-b31a-4eb3-b429-e039120e488a -CLIENT_SECRET = V288Q~P1lFMvvX9Xnkx2pLixK~GOREH983Owqc1E -RELAY_ROOT = https://ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-uks-01/ -RELAYURI = "ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net" -RELAYPATH = "ar-hc-lz-pedw-ppe-uks-01" -# RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-ukw-01/ -# RELAYURI = "ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net" -# RELAYPATH = "ar-hc-lz-pedw-ppe-ukw-01" -CRMURL = "ppcrm2016.llcdt.gov.wales/PPPINSWales" +# # //New PreProd +# CLIENT_ID = ab6c4678-b31a-4eb3-b429-e039120e488a +# CLIENT_SECRET = V288Q~P1lFMvvX9Xnkx2pLixK~GOREH983Owqc1E +# RELAY_ROOT = https://ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-uks-01/ +# RELAYURI = "ar-ns-lz-pedw-ppe-uks-01.servicebus.windows.net" +# RELAYPATH = "ar-hc-lz-pedw-ppe-uks-01" +# # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-ppe-ukw-01/ +# # RELAYURI = "ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net" +# # RELAYPATH = "ar-hc-lz-pedw-ppe-ukw-01" +# CRMURL = "ppcrm2016.llcdt.gov.wales/PPPINSWales" # //Prod Oauth WGO @@ -48,6 +48,17 @@ CRMURL = "ppcrm2016.llcdt.gov.wales/PPPINSWales" # RELAYPATH = "prod-pedw-hc" # CRMURL = "crm2016.llc.gov.wales/PEDW" +# //New Prod +# CLIENT_ID = 3e4141a3-1fbd-454e-98f0-7f3a4f14a3cc +# CLIENT_SECRET = tFk8Q~E.R-HFjROTu1sRKqwb_ONzy05uPYoF6awR +# RELAY_ROOT = https://ar-ns-lz-pedw-prod-uks-01.servicebus.windows.net/ar-hc-lz-pedw-prod-uks-01/ +# RELAYURI = "ar-ns-lz-pedw-prod-uks-01.servicebus.windows.net" +# RELAYPATH = "ar-hc-lz-pedw-prod-uks-01" +# # RELAY_ROOT = https://ar-ns-lz-pedw-ppe-ukw-01.servicebus.windows.net/ar-hc-lz-pedw-prod-ukw-01/ +# # RELAYURI = "ar-ns-lz-pedw-prod-ukw-01.servicebus.windows.net" +# # RELAYPATH = "ar-hc-lz-pedw-prod-ukw-01" +# CRMURL = "crm2016.llcdt.gov.wales/PEDW" + //GOOGLE_TAG_MANAGER = GTM-T78CBC3 GOOGLE_TAG_MANAGER = G-GTWW3JT03Z @@ -58,8 +69,9 @@ SHOWMAPS = false API_ROOT = "http://localhost:3000" CY_API_ROOT = "http://cymru.local:3000" I18N_DOMAIN = "cymru.local" -DOCAPI_OFFLINE = "12:00:00,14:00:00" -SHOWFILTERDOCS = false +# DOCAPI_OFFLINE = "12:00:00,14:00:00" +DOCAPI_OFFLINE = "02:00:00,04:00:00" +SHOWFILTERDOCS = true // Next Auth vars @@ -68,18 +80,20 @@ NEXTAUTH_URL_INTERNAL = $API_ROOT NEXTAUTH_SECRET = SuperSecret // CNR sql server -# DATABASE_URL = sqlserver://sql-srv-plt-pedw-cnr-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword +DATABASE_URL = sqlserver://sql-srv-plt-pedw-cnr-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword // dev test sql server # DATABASE_URL = sqlserver://pedw-dev-test-sql-svr.database.windows.net:1433;database=PEDWDev;user=RobBondSQL;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword -# DATABASE_URL = sqlserver://sql-srv-plt-pedw-dev-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword + DATABASE_URL = sqlserver://sql-srv-plt-pedw-dev-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword // Pre prod sql server -DATABASE_URL = sqlserver://sql-srv-plt-pedw-ppe-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustservercertificate=true;hostnameincertificate=*.database.windows.net;logintimeout=30;authentication=SqlPassword +# DATABASE_URL = sqlserver://sql-srv-plt-pedw-ppe-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustservercertificate=true;hostnameincertificate=*.database.windows.net;logintimeout=30;authentication=SqlPassword // Prod sql server # DATABASE_URL = sqlserver://pp-pedw-sql.database.windows.net:1433;database=PEDWPreProd;user=RobBondSQL;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword +// Prod sql server +# DATABASE_URL = sqlserver://sql-srv-plt-pedw-prod-uks-01.database.windows.net:1433;database=PEDW;user=PedwSqlAdmin;password=GhWKr62F5sQ69dZx;encrypt=true;trustServerCertificate=true;hostNameInCertificate=*.database.windows.net;loginTimeout=30;authentication=ActiveDirectoryPassword SECRET = SuperSecret @@ -91,24 +105,24 @@ AZURE_TENANT_ID = $TENANT AZURE_CLIENT_SECRET = $CLIENT_SECRET // CNR key -# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwcnruks" -# AZURE_STORAGE_ACCOUNT_KEY = hRffHq4IwctpaTKdS/U33Xq6nyTDF1t++WJgIwsw7gzstktZin/rRwbTIAL9KKqesVsK7EHrTTG6+ASt4+7skw== -# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwcnruks.blob.core.windows.net +AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwcnruks" +AZURE_STORAGE_ACCOUNT_KEY = hRffHq4IwctpaTKdS/U33Xq6nyTDF1t++WJgIwsw7gzstktZin/rRwbTIAL9KKqesVsK7EHrTTG6+ASt4+7skw== +AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwcnruks.blob.core.windows.net // new dev key -# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwdevuks" -# AZURE_STORAGE_ACCOUNT_KEY = MmrsrCjBfop9pI2oImsP/+lJUWU2DrXsAB8nq5bOVROTmPovSGxjCjKw9+TAFr00k8WDUK9r6mVx+AStcMLyAA== -# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwdevuks.blob.core.windows.net +AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwdevuks" +AZURE_STORAGE_ACCOUNT_KEY = MmrsrCjBfop9pI2oImsP/+lJUWU2DrXsAB8nq5bOVROTmPovSGxjCjKw9+TAFr00k8WDUK9r6mVx+AStcMLyAA== +AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwdevuks.blob.core.windows.net // New test key -# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwtestuks" -# AZURE_STORAGE_ACCOUNT_KEY = bqJAz5pYQVGee8dnVhlsqW+xHwinNTjgY2AmojNyB+d4uAotMR20WcO4Op13yB+9dFaXAkkjtIA4+AStHT/IYg== -# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwtestuks.blob.core.windows.net +AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwtestuks" +AZURE_STORAGE_ACCOUNT_KEY = bqJAz5pYQVGee8dnVhlsqW+xHwinNTjgY2AmojNyB+d4uAotMR20WcO4Op13yB+9dFaXAkkjtIA4+AStHT/IYg== +AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwtestuks.blob.core.windows.net // New preprod key -AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwppeuks" -AZURE_STORAGE_ACCOUNT_KEY = B4GRKr+cA9b9mNM/GHFivzhzflJIZltG8bMmooXlYvGYySPAspTTHistAT30sHipnR+hh6dqUc9q+ASttAjPRQ== -AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwppeuks.blob.core.windows.net +# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwppeuks" +# AZURE_STORAGE_ACCOUNT_KEY = B4GRKr+cA9b9mNM/GHFivzhzflJIZltG8bMmooXlYvGYySPAspTTHistAT30sHipnR+hh6dqUc9q+ASttAjPRQ== +# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwppeuks.blob.core.windows.net // PROD key @@ -116,6 +130,11 @@ AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwppeuks.blob.core.windows.net # AZURE_STORAGE_ACCOUNT_KEY = koZ46STRqapSa2Dod8MLL6aju1eYLhhyJ6DXpCLMTnFLJvbDT6CHUv/jwr5U/Ta8a60MWzwToHQy+AStADO7sg== # AZURE_PEDW_STORAGE_ENDPOINT = https://pedwprod.blob.core.windows.net +# // New PROD key +# AZURE_STORAGE_ACCOUNT_NAME = "sapltpedwproduks" +# AZURE_STORAGE_ACCOUNT_KEY = OfV9MFqXcLLPam9GhEdMWadIOwIzhc5hd5TUqzIuQoswFdtV4ybaemjatSv+Kht0Ny1qQKjLplwY+AStUTZJrg== +# AZURE_PEDW_STORAGE_ENDPOINT = https://sapltpedwproduks.blob.core.windows.net + AZURE_PEDW_CONTAINER = "pedwapplications" AZURE_PEDW_QUEUE_ENDPOINT = https://$AZURE_STORAGE_ACCOUNT_NAME.queue.core.windows.net @@ -146,4 +165,8 @@ NEXT_PUBLIC_APP_INSIGHT = InstrumentationKey=a41b91bf-f7dc-4f44-bb66-a67df4eee43 //NEXT_PUBLIC_APP_INSIGHT = InstrumentationKey=61f358c2-8075-4164-b897-17bc6dd31fee;IngestionEndpoint=https://ukwest-0.in.applicationinsights.azure.com/;LiveEndpoint=https://ukwest.livediagnostics.monitor.azure.com/;ApplicationId=0c297349-396b-4dc6-8b56-85f5c680adc6 -HIDEERRORLOGS = false \ No newline at end of file +HIDEERRORLOGS = false + +SHOWSIPS = true + +ALLOWED_IPS=::1,203.0.113.42,198.51.100.17 diff --git a/.vscode/launch.json b/.vscode/launch.json index 8f9df645..f961904e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ "command": "npm run dev" }, {"name": "Launch Chrome against localhost", - "type": "pwa-chrome", + "type": "chrome", "request": "launch", "url": "http://localhost:3000", "webRoot": "${workspaceFolder}" diff --git a/actions/azurestorage.js b/actions/azurestorage.js index 6b1791c1..f83b1850 100644 --- a/actions/azurestorage.js +++ b/actions/azurestorage.js @@ -309,7 +309,7 @@ export const createRepBlob = async (formContent, containerName, caseref) => { const tags = { containerid: containerName, - caseID: formContent.caseRef, + caseID: formContent.ticketnumber, blobType: "Representation", }; @@ -317,7 +317,7 @@ export const createRepBlob = async (formContent, containerName, caseref) => { const withTags = await blockBlobClient.setTags(tags); const withMeta = await blockBlobClient.setMetadata(tags); - return formContent.pinswg_name; + return formContent.ticketnumber; }; export const createAppealPDFBlob = async ( @@ -1702,3 +1702,100 @@ export const listBlobHierarchical = async ( } } }; + +function formatTimeSince(date) { + if (!date) return "Unknown date"; + + const now = new Date(); + const diffMs = now - date; + const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); + + if (diffDays < 7) { + return `${diffDays} day${diffDays !== 1 ? "s" : ""} ago`; + } else { + const diffWeeks = Math.floor(diffDays / 7); + return `${diffWeeks} week${diffWeeks !== 1 ? "s" : ""} ago`; + } +} + +function formatDateDisplay(date) { + return date + ? `${date.toLocaleString("en-GB")} (${formatTimeSince(date)})` + : "Unknown"; +} + +export async function listBlobHierarchicalForUser(containerClient) { + const blobNames = []; + for await (const blob of containerClient.listBlobsFlat()) { + const lastModifiedDate = blob.properties?.lastModified || null; + const createdOnDate = blob.properties?.createdOn || null; + + let displayDate = ""; + + if (createdOnDate && lastModifiedDate) { + if ( + createdOnDate.toDateString() === lastModifiedDate.toDateString() + ) { + // Same day — show just one + displayDate = `Date: ${formatDateDisplay(lastModifiedDate)}`; + } else { + // Different days — show both + displayDate = `Created: ${formatDateDisplay( + createdOnDate + )}, Modified: ${formatDateDisplay(lastModifiedDate)}`; + } + } else if (lastModifiedDate) { + displayDate = `Modified: ${formatDateDisplay(lastModifiedDate)}`; + } else if (createdOnDate) { + displayDate = `Created: ${formatDateDisplay(createdOnDate)}`; + } else { + displayDate = "Unknown date"; + } + + blobNames.push({ + name: blob.name, + size: blob.properties.contentLength || 0, + lastModified: lastModifiedDate + ? lastModifiedDate.toISOString() + : null, + createdOn: createdOnDate ? createdOnDate.toISOString() : null, + displayDate, + }); + } + return blobNames; +} + +export async function listContainersForUser( + blobServiceClient, + containerNamePrefix, + emailAddress +) { + const options = { + includeDeleted: false, + includeMetadata: true, + includeSystem: true, + prefix: containerNamePrefix, + }; + + const results = []; + + for await (const containerItem of blobServiceClient.listContainers( + options + )) { + const containerClient = blobServiceClient.getContainerClient( + containerItem.name + ); + const blobNames = await listBlobHierarchicalForUser( + containerClient + ).catch(console.error); + + if (blobNames && blobNames.length > 0) { + results.push({ + container: containerItem.name, + blobs: blobNames, + }); + } + } + + return results; // array of non-empty containers +} diff --git a/actions/index.js b/actions/index.js index 072e4fa0..9f780704 100644 --- a/actions/index.js +++ b/actions/index.js @@ -1492,7 +1492,7 @@ export const deleteMyRepresentationsFromBlob = ( }); }; -export const deleteWatchedCases = (watchedCaseID) => { +export const deleteWatchedCases = async (watchedCaseID) => { var queryUrl = "/api/endpoint/deletewatchedcasesproxy_api?watchedCaseID=" + watchedCaseID; @@ -1501,14 +1501,12 @@ export const deleteWatchedCases = (watchedCaseID) => { url: queryUrl, }; - return axios(config) - .then((res) => { - //console.log("deleted ", res.data); - return res.data; - }) - .catch((error) => { - consoleLogger(error); - }); + try { + const res = await axios(config); + return res.data; + } catch (error) { + consoleLogger(error); + } }; export const createAccount = (formValues) => { diff --git a/components/breadcrumbs.js b/components/breadcrumbs.js index 95b38e46..8bbb5444 100644 --- a/components/breadcrumbs.js +++ b/components/breadcrumbs.js @@ -497,20 +497,27 @@ const Breadcrumbs = (props) => {
  • - {viewAllKey == + {(currentView.currentView.viewKey || + router.query.key) == "awaitingSubmissionDetails" && t( "myportal:awatitingsubmission-card-title" )} - {viewAllKey == "watchedCases" && + {(currentView.currentView.viewKey || + router.query.key) == "watchedCases" && t("myportal:watchedcases-card-title")} - {viewAllKey == "myCases" && + {(currentView.currentView.viewKey || + router.query.key) == "myCases" && t("myportal:mycases-card-title")} - {viewAllKey == "myRepresentations" && + {(currentView.currentView.viewKey || + router.query.key) == + "myRepresentations" && t( "myportal:myrepresentations-card-title" )} - {viewAllKey == "mySubmittedReps" && + {(currentView.currentView.viewKey || + router.query.key) == + "mySubmittedReps" && "Submitted representations"}
  • @@ -545,19 +552,13 @@ const Breadcrumbs = (props) => {
  • {t("common:breadcrumb-search-results")} @@ -724,10 +725,10 @@ const Breadcrumbs = (props) => {
  • {t("common:breadcrumb-case-reference")}:{" "} - { - props.props.currentView.caseReference - .currentReference - } + {props.props.currentView.caseReference + .currentReference || + props.props.searchResultsObj + .searchResultsObj.value[0].title}
  • )} @@ -811,10 +812,10 @@ const Breadcrumbs = (props) => {
  • {t("common:breadcrumb-case-reference")}:{" "} - { - props.props.currentView.caseReference - .currentReference - } + {props.props.currentView.caseReference + .currentReference || + props.props.searchResultsObj + .searchResultsObj.value[0].title}
  • )} @@ -1075,10 +1076,10 @@ const Breadcrumbs = (props) => {
  • {t("common:breadcrumb-case-reference")}:{" "} - { - props.props.currentView.caseReference - .currentReference - } + {props.props.currentView.caseReference + .currentReference || + props.props.searchResultsObj + .searchResultsObj.value[0].title}
  • )} diff --git a/components/case.js b/components/case.js index ae88b888..915dc95d 100644 --- a/components/case.js +++ b/components/case.js @@ -27,6 +27,7 @@ const Case = (props) => { watchedCasesDetails={props.watchedCasesDetails} awaitingSubmission={props.awaitingSubmission} caseReference={props.caseReference} + ticketnumber={props.ticketnumber} currentType={props.currentType} appealTypeID={props.appealTypeID} searchResultsObj={props.searchResultsObj} diff --git a/components/case/documents.js b/components/case/documents.js index 315b15b3..1a31a18d 100644 --- a/components/case/documents.js +++ b/components/case/documents.js @@ -19,7 +19,7 @@ import { setCurrentPage } from "../../store/currentView/action"; import { setDocumentDetails } from "../../store/searchOutput/action"; const DocumentDetails = (props) => { - let { t } = useTranslation(); + let { t, lang } = useTranslation(); const firstRender = useRef(false); const { incidentid, @@ -419,7 +419,7 @@ const DocumentDetails = (props) => { ] + '")].value_cy', json: transLookup, - sanbox: {}, + eval: true, }) : detailsObj[ "pinswg_isharedocumentlocations@OData.Community.Display.V1.FormattedValue" @@ -507,7 +507,7 @@ const DocumentDetails = (props) => {

    @@ -584,8 +584,8 @@ const DocumentDetails = (props) => { '$..[?(@ && @.value=="' + item.pinswg_isharedocumentlocationsLabel + '")].value_cy', - jsonL: transLookup, - sanbox: {}, + json: transLookup, + eval: true, }) : item.pinswg_isharedocumentlocationsLabel || t( @@ -611,7 +611,7 @@ const DocumentDetails = (props) => { setCurrentPage(1); }} > - {t("case:documents-filter-button")} + {t("search:filter-documents-label")}
    {documentDetailsObj["@odata.count"] > 5 && ( @@ -1068,6 +1068,7 @@ const DocumentDetails = (props) => { orderByState, getDocumentTypes, getDocumentResults, + lang, ]); return (
    diff --git a/components/case/representation/index.js b/components/case/representation/index.js index 3508ff40..27b9092c 100644 --- a/components/case/representation/index.js +++ b/components/case/representation/index.js @@ -65,6 +65,7 @@ let MakeRepresentation = (props) => { showQuestionnaireSection, initialValues, setCurrentReference, + ticketnumber, } = props; const formObj = props.props.form; let setCaseQueryObj = props[currentType] || {}; @@ -427,6 +428,12 @@ let MakeRepresentation = (props) => { currentType={currentType} casesObj={casesObj} caseReference={caseReference} + ticketnumber={ticketnumber} + setRepFileName={setRepFileName} + updateRepresentation={updateRepresentation} + setSavingStatus={setSavingStatus} + savingStatus={savingStatus} + setCurrentReference={setCurrentReference} /> ); } @@ -590,6 +597,26 @@ let MakeRepresentation = (props) => { return deduplicate(mergedFiles); }; + const buildAddressStr = (detailsObj) => { + const toTitleCase = (str) => + str.toLowerCase().replace(/\b\w/g, (char) => char.toUpperCase()); + + return [ + detailsObj?.pinswg_siteaddressline1 || + detailsObj?.pinswg_addressline1, + detailsObj?.pinswg_siteaddressline2 || + detailsObj?.pinswg_addressline2, + detailsObj?.pinswg_siteaddresstown || + detailsObj?.pinswg_addresstown, + detailsObj?.pinswg_siteaddresspostcode || + detailsObj?.pinswg_postcode, + detailsObj?.pinswg_siteaddresscounty || + detailsObj?.pinswg_addresscounty, + ] + .filter((v) => !!v && v.trim()) // remove empty/whitespace-only values + .map((v) => toTitleCase(v.trim())) // title-case each segment + .join(" "); + }; const updateRepresentation = async ( values, sendSavedEmail, diff --git a/components/case/representation/representationAgent.js b/components/case/representation/representationAgent.js index c561500a..14368697 100644 --- a/components/case/representation/representationAgent.js +++ b/components/case/representation/representationAgent.js @@ -197,7 +197,8 @@ const RepAgent = (props) => { "myrepresentations:add-files-label" )} ticketnumber={ - props.props.caseReference + props.currentView.caseReference + .ticketnumber } hint={"sdsd"} fileList={ diff --git a/components/case/representation/representationAppellant.js b/components/case/representation/representationAppellant.js index b8b54ec9..59b51e25 100644 --- a/components/case/representation/representationAppellant.js +++ b/components/case/representation/representationAppellant.js @@ -189,7 +189,10 @@ const RepAppellant = (props) => { label={t( "myrepresentations:add-files-label" )} - ticketnumber={props.props.caseReference} + ticketnumber={ + props.currentView.caseReference + .ticketnumber + } hint={"sdsd"} fileList={ props.currentView.fileList diff --git a/components/case/representation/representationCapacitySelection.js b/components/case/representation/representationCapacitySelection.js index 3f5e5d2b..a349bdd0 100644 --- a/components/case/representation/representationCapacitySelection.js +++ b/components/case/representation/representationCapacitySelection.js @@ -36,6 +36,9 @@ let RepCapacitySelection = (props) => { currentType={currentType} casesObj={casesObj} caseReference={props.props.caseReference} + ticketnumber={ + props.props.currentView.caseReference.ticketnumber + } searchResultsObj={props.props.searchResultsObj} myRepresentations={props.props.myRepresentations} props={props} diff --git a/components/case/representation/representationComplete.js b/components/case/representation/representationComplete.js index 0bfa4b12..4e8791c2 100644 --- a/components/case/representation/representationComplete.js +++ b/components/case/representation/representationComplete.js @@ -65,7 +65,7 @@ const RepComplete = (props) => { ), sendRepCompleteMessage( props.props.props.props.accountDetails.containerID, - props.props.currentView.caseReference.currentReference, + props.props.currentView.caseReference.ticketnumber, props.repFormData.repfile_name ), sendEmail(templateId, emailAddress, personalisation, reference), diff --git a/components/case/representation/representationDetails.js b/components/case/representation/representationDetails.js index e3947f14..a3931833 100644 --- a/components/case/representation/representationDetails.js +++ b/components/case/representation/representationDetails.js @@ -10,7 +10,7 @@ const RepDetails = (props) => { const { currentType, casesObj, appealType } = props; - let { caseReference } = props; + let { caseReference, ticketnumber } = props; let setCaseDetailsObj = router.query.hasOwnProperty("state") ? router.query.state == "edit" @@ -29,7 +29,7 @@ const RepDetails = (props) => { : caseReference; detailsObj = jsonpath({ - path: '$..[?(@ && @.pinswg_name=="' + caseReference + '")]', + path: '$..[?(@ && @.ticketnumber=="' + ticketnumber + '")]', json: setCaseDetailsObj, eval: true, }); diff --git a/components/case/representation/representationInterestedPartyPerson.js b/components/case/representation/representationInterestedPartyPerson.js index d77fd6d2..267aac02 100644 --- a/components/case/representation/representationInterestedPartyPerson.js +++ b/components/case/representation/representationInterestedPartyPerson.js @@ -189,7 +189,8 @@ const RepInterestedPartyPerson = (props) => { "myrepresentations:add-files-label" )} ticketnumber={ - props.props.caseReference + props.currentView.caseReference + .ticketnumber } hint={"sdsd"} fileList={ diff --git a/components/case/representation/representationLPA.js b/components/case/representation/representationLPA.js index 1d38c9e9..b79257d3 100644 --- a/components/case/representation/representationLPA.js +++ b/components/case/representation/representationLPA.js @@ -354,7 +354,7 @@ let RepLPA = (props) => { "myrepresentations:add-files-label" )} ticketnumber={ - props.props.caseReference + props.currentView.caseReference.ticketnumber } hint={"sdsd"} fileList={ diff --git a/components/case/representation/representationLPACapacitySelection.js b/components/case/representation/representationLPACapacitySelection.js index bfc2260e..47122ad9 100644 --- a/components/case/representation/representationLPACapacitySelection.js +++ b/components/case/representation/representationLPACapacitySelection.js @@ -34,6 +34,7 @@ let RepLPACapacitySelection = (props) => { casesObj={casesObj} detailsObj={detailsObj} caseReference={props.props.caseReference} + ticketnumber={props.props.ticketnumber} searchResultsObj={props.props.searchResultsObj} props={props.props} />{" "} diff --git a/components/case/representation/representationLPADetails.js b/components/case/representation/representationLPADetails.js index 55c19618..1015f95e 100644 --- a/components/case/representation/representationLPADetails.js +++ b/components/case/representation/representationLPADetails.js @@ -8,7 +8,7 @@ const RepLPADetails = (props) => { const router = useRouter(); const { locale } = router; - const { currentType, casesObj, caseReference } = props; + const { currentType, casesObj, caseReference, ticketnumber } = props; let setCaseDetailsObj = router.query.hasOwnProperty("state") ? router.query.state == "edit" @@ -21,7 +21,7 @@ const RepLPADetails = (props) => { var detailsObj = {}; detailsObj = jsonpath({ - path: '$..[?(@ && @.pinswg_name=="' + caseReference + '")]', + path: '$..[?(@ && @.ticketnumber=="' + ticketnumber + '")]', json: setCaseDetailsObj, eval: true, }); diff --git a/components/case/representation/representationLandowner.js b/components/case/representation/representationLandowner.js index 8029b788..90782bf6 100644 --- a/components/case/representation/representationLandowner.js +++ b/components/case/representation/representationLandowner.js @@ -84,7 +84,10 @@ const RepLandOwner = (props) => { label={t( "myrepresentations:add-files-label" )} - ticketnumber={props.props.caseReference} + ticketnumber={ + props.currentView.caseReference + .ticketnumber + } hint={"sdsd"} fileList={[]} setFilesForRepresentation={[]} diff --git a/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_enforcement.js b/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_enforcement.js index d8fdfbe0..92437b28 100644 --- a/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_enforcement.js +++ b/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_enforcement.js @@ -1213,7 +1213,10 @@ let Enforcement_Questionnaire = (props) => { name={"representationDocuments"} id={"representationDocuments"} label={t("myrepresentations:add-files-label")} - ticketnumber={props.props.props.caseReference} + ticketnumber={ + props.props.currentView.caseReference + .ticketnumber + } hint={"sdsd"} fileList={ props.currentView.fileList diff --git a/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_s78.js b/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_s78.js index ae86e2b8..5c10936a 100644 --- a/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_s78.js +++ b/components/case/representation/representationQuestionnaires/representationLPAQuestionnaire_s78.js @@ -1022,7 +1022,10 @@ let S78_Questionnaire = (props) => { name={"representationDocuments"} id={"representationDocuments"} label={t("myrepresentations:add-files-label")} - ticketnumber={props.props.props.caseReference} + ticketnumber={ + props.props.currentView.caseReference + .ticketnumber + } hint={"sdsd"} fileList={ props.currentView.fileList diff --git a/components/case/summary.js b/components/case/summary.js index 35a485b8..f30aa0fd 100644 --- a/components/case/summary.js +++ b/components/case/summary.js @@ -76,6 +76,7 @@ const CaseSummary = (props) => { currentView, messagesObj, docsOffline, + ticketnumber, } = props; let appealTypeID = props.appealTypeID || router.query.appealType; @@ -233,13 +234,13 @@ const CaseSummary = (props) => { currentType == "searchResultsObj" ? (casesObj = jsonpath({ - path: '$..[?(@ && @.title=="' + caseReference + '")]', + path: '$..[?(@ && @.ticketnumber=="' + ticketnumber + '")]', json: searchResultsObj, eval: true, })) : currentType == "watchedCases" ? (casesObj = jsonpath({ - path: '$..[?(@ && @.pinswg_title=="' + caseReference + '")]', + path: '$..[?(@ && @.ticketnumber=="' + ticketnumber + '")]', json: setCaseQueryObj, eval: true, })) @@ -251,7 +252,7 @@ const CaseSummary = (props) => { })) : currentType == "directResultsObj" ? (casesObj = jsonpath({ - path: '$..[?(@ && @.ticketnumber=="' + caseReference + '")]', + path: '$..[?(@ && @.ticketnumber=="' + ticketnumber + '")]', json: setCaseQueryObj, eval: true, })) @@ -1867,7 +1868,10 @@ const CaseSummary = (props) => { id="case-documents" > { currentView, showMap ) { - const id = getFormCollectionByID(appealTypeID).PrimaryIdAttribute; + const id = getFormCollectionByID( + appealTypeID || setCaseQueryObj.value[0].pinswg_appealcasetype + ).PrimaryIdAttribute; const Component = CaseTypes[capitalizeFirstLetter(id)]; @@ -1955,7 +1961,9 @@ const CaseSummary = (props) => { useEffect(() => { const linkCaseObj = async () => { - let docObj = await getLinkedCases(incidentid).then((data) => { + let docObj = await getLinkedCases( + incidentid || setCaseQueryObj.value[0].incidentid + ).then((data) => { //console.log(data); setCurrentLinkedCases(data); return data; diff --git a/components/case/summaryTypes/pinswg_dnsid.js b/components/case/summaryTypes/pinswg_dnsid.js index 0ea6b66e..16786693 100644 --- a/components/case/summaryTypes/pinswg_dnsid.js +++ b/components/case/summaryTypes/pinswg_dnsid.js @@ -129,7 +129,6 @@ const Pinswg_dnsid = (props) => { "pinswg_appealcasetype@OData.Community.Display.V1.FormattedValue" ] + '")].value_cy', - json: transLookup, eval: true, }) diff --git a/components/dnssearchresults.js b/components/dnssearchresults.js index c70dd317..15c8dcd0 100644 --- a/components/dnssearchresults.js +++ b/components/dnssearchresults.js @@ -4,8 +4,14 @@ import CRMError from "./crmError"; import DNSSearchResults from "./search/dnssearchresults"; export default function Search(props) { - const { searchString, searchResultsObj, myportal, watchedCases, showMap } = - props; + const { + searchString, + searchResultsObj, + myportal, + watchedCases, + showMap, + showLoginCheck, + } = props; let { t } = useTranslation(); const router = useRouter(); @@ -41,6 +47,7 @@ export default function Search(props) { myportal={myportal} watchedCases={watchedCases} showMap={showMap} + showLoginCheck={showLoginCheck} />
    diff --git a/components/homepage/casecomment.js b/components/homepage/casecomment.js index eace402d..258063b7 100644 --- a/components/homepage/casecomment.js +++ b/components/homepage/casecomment.js @@ -8,17 +8,7 @@ export default function CaseComment() { const { locale } = router; return (
    -
    -

    - {t("home:casescomment-card-title")} -

    - -

    - {t("home:casescomment-card-paragraph-three")} -

    -

    - {t("home:casescomment-card-paragraph-four")} -

    +

    {t("home:casescomment-card-paragraph-one")}{" "}

    -

    - {t("home:casescomment-card-paragraph-two")} -

    -

    - {t("home:watch-case-card-title")} -

    -

    - {t("home:watch-case-paragraph-one")} -

    + {/*

    {t("home:casescomment-card-paragraph-two")}

    */} diff --git a/components/homepage/login.js b/components/homepage/login.js index 6c67dfcb..496f37f0 100644 --- a/components/homepage/login.js +++ b/components/homepage/login.js @@ -78,49 +78,24 @@ let Login = (props) => {

    {t("home:signin-benefits-paragraph")}

    -

    - {/* {t("home:login-card-title")} */} - {t("home:login-card-title-temp")} -

    {" "} - {/*
    -
    - {session && "Signed in as " + session.user?.email} -
    -
    - - {!session && ( - - )} - {session && ( - - )} -
    */} -

    - {t("home:login-comingsoon-temp-1")}{" "} -

    - {/*

    - {t("home:login-comingsoon-temp-1a")}{" "} -

    */} +
      +
    • + {" "} + + {" "} + {t("home:login-card-title-temp")}{" "} + {" "} + {t("home:login-comingsoon-temp-1")} +
    • +
    • + {t("home:casescomment-card-title")}{" "} + {t("home:casescomment-card-paragraph-two")} +
    • +
    • + {t("home:watch-case-card-title")}{" "} + {t("home:watch-case-paragraph-one")} +
    • +

    {t("home:login-comingsoon-temp-2")} @@ -178,9 +153,17 @@ let Login = (props) => { +

    + {t("home:casescomment-card-paragraph-one")}{" "} + + {t("home:login-contact-email")} + +

    -
    ); diff --git a/components/myportal.js b/components/myportal.js index 495bb19d..6a15097b 100644 --- a/components/myportal.js +++ b/components/myportal.js @@ -168,6 +168,7 @@ const MyPortal = (props) => { watchedCases={props.watchedCases} isLPA={isLPA} myReps={false} + accountDetails={props.accountDetails} /> )} {props.myRepresentations.hasOwnProperty( diff --git a/components/myportal/awaitingsubmission.js b/components/myportal/awaitingsubmission.js index dc79fc81..e29e3b0b 100644 --- a/components/myportal/awaitingsubmission.js +++ b/components/myportal/awaitingsubmission.js @@ -37,9 +37,8 @@ const AwaitingSubmission = (props) => { (router.locale != "en" ? "/" + router.locale + - "/fymhorth/gweldpopeth" - : "/myportal/viewall") + - "?viewKey=awaitingSubmission" + "/fymhorth/gweldpopeth?key=awaitingSubmission" + : "/myportal/viewall?key=awaitingSubmission" } className="govuk-link--no-underline" onClick={() => { diff --git a/components/myportal/awaitingsubmissionfromblob.js b/components/myportal/awaitingsubmissionfromblob.js index 9430f83e..33f9e6f4 100644 --- a/components/myportal/awaitingsubmissionfromblob.js +++ b/components/myportal/awaitingsubmissionfromblob.js @@ -351,12 +351,11 @@ const AwaitingSubmissionFromBlob = (props) => {
    { diff --git a/components/myportal/mycases.js b/components/myportal/mycases.js index 6e9374f7..e8b3d19b 100644 --- a/components/myportal/mycases.js +++ b/components/myportal/mycases.js @@ -29,11 +29,11 @@ const MyCases = (props) => {
    { diff --git a/components/myportal/myrepresentations.js b/components/myportal/myrepresentations.js index f2999e83..17430582 100644 --- a/components/myportal/myrepresentations.js +++ b/components/myportal/myrepresentations.js @@ -34,12 +34,11 @@ const MyRepresentations = (props) => {
    { diff --git a/components/myportal/myrepresentationsfromblob.js b/components/myportal/myrepresentationsfromblob.js index 32786575..79383c82 100644 --- a/components/myportal/myrepresentationsfromblob.js +++ b/components/myportal/myrepresentationsfromblob.js @@ -36,9 +36,8 @@ const MyRepresentations = (props) => { (router.locale != "en" ? "/" + router.locale + - "/fymhorth/gweldpopeth" - : "/myportal/viewall") + - "?viewKey=myRepresentations" + "/fymhorth/gweldpopeth?key=myRepresentations" + : "/myportal/viewall?key=myRepresentations" } className="govuk-link--no-underline" onClick={() => { diff --git a/components/myportal/mysubmittedrepresentations.js b/components/myportal/mysubmittedrepresentations.js index ec1d5066..98d9bf0c 100644 --- a/components/myportal/mysubmittedrepresentations.js +++ b/components/myportal/mysubmittedrepresentations.js @@ -40,12 +40,11 @@ const MySubmittedReps = (props) => {
    { diff --git a/components/myportal/servicebanner.js b/components/myportal/servicebanner.js index ac7be623..1cafe044 100644 --- a/components/myportal/servicebanner.js +++ b/components/myportal/servicebanner.js @@ -43,6 +43,11 @@ const ServiceBanner = (props) => { {portalLogoLink.includes(router.pathname) ? ( { ) : ( { deleteWatchedCases(caseID) .then((data) => data) .then(() => { - getWatchedCasesProxy(cookies.pinsUser).then((data) => { + getWatchedCasesProxy( + props.accountDetails.loggedinUserId + ).then((data) => { let showWatchedCases = (submittedArr) => { const required = submittedArr.value.filter((el) => { return ( @@ -134,19 +136,15 @@ const TopThree = (props) => { }); }; - data = showWatchedCases(data); + let filteredWatchedCases = showWatchedCases(data); - data.value.sort(function compare(a, b) { - var dateA = new Date(a.createdon); - var dateB = new Date(b.createdon); - return dateB - dateA; - }); - setWatchedCases(data), - getDetailsProxy(data, "myWatchedCases").then( - (data) => { - setWatchedCasesDetails(data); - } - ); + setWatchedCases(filteredWatchedCases), + getDetailsProxy( + filteredWatchedCases, + "myWatchedCases" + ).then((data) => { + setWatchedCasesDetails(data); + }); }); }); @@ -328,9 +326,8 @@ const TopThree = (props) => { : showTopThreeArr[key][ "_pinswg_case_value@OData.Community.Display.V1.FormattedValue" ] - : showTopThreeArr[key][ - "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue" - ], + : showTopThreeArr[key] + .ticketnumber, "currentType": topThreeType, "incidentid": getIncidentId( @@ -344,15 +341,18 @@ const TopThree = (props) => { }); }} > - {topThreeType != "watchedCases" + {showTopThreeArr[key].pinswg_title} + {/* {topThreeType != "watchedCases" ? topThreeType != "myRepresentations" - ? showTopThreeArr[key].ticketnumber + ? topThreeType == "mySubmittedReps" + ? showTopThreeArr[key].pinswg_title + : showTopThreeArr[key].ticketnumber : showTopThreeArr[key][ "_pinswg_case_value@OData.Community.Display.V1.FormattedValue" ] : showTopThreeArr[key][ "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue" - ]}{" "} + ]}{" "} */} )} {topThreeType == "watchedCases" && !props.myReps && ( diff --git a/components/myportal/topthree_reps.js b/components/myportal/topthree_reps.js index 1b9ab569..e048770b 100644 --- a/components/myportal/topthree_reps.js +++ b/components/myportal/topthree_reps.js @@ -193,21 +193,26 @@ const TopThree = (props) => { {showTopThreeArr[key].hasOwnProperty("repComplete") ? ( {showTopThreeArr[key].pinswg_name} ) : ( - { setCurrentReference({ @@ -223,10 +228,24 @@ const TopThree = (props) => { "repDetails": showTopThreeArr[key], }); isLPA && setRepresentationCapacity("LPA"); + router.push({ + pathname: + router.locale == "cy" + ? "/fymhorth/representation" + : "/myportal/representation", + query: { + case: showTopThreeArr[key] + .ticketnumber, + state: "edit", + created: + showTopThreeArr[key] + .repfile_name, + }, + }); }} > {showTopThreeArr[key].pinswg_name} - + )} {!showTopThreeArr[key].hasOwnProperty( "repComplete" @@ -234,13 +253,13 @@ const TopThree = (props) => {
    )} - {viewAllKey == "myRepresentations" && ( + {currentViewKey == "myRepresentations" && (
    )} - {viewAllKey == "watchedCases" && ( -
    + {currentViewKey == "watchedCases" && ( +
    - {viewAllKey == "awaitingSubmissionDetails" ? ( + {currentViewKey == + "awaitingSubmissionDetails" ? (
    - {viewAllKey != + {currentViewKey != "awaitingSubmissionDetails" ? (
    - {viewAllKey == "myRepresentations" ? ( + {currentViewKey == "myRepresentations" ? (
    + + {(currentViewKey == "watchedCases" || + currentViewKey == + "awaitingSubmissionDetails" || + currentViewKey == "myRepresentations") && ( +
    + )}
    {showSpinnerState == true ? (
    diff --git a/components/myportal/watchedcases.js b/components/myportal/watchedcases.js index e7d8fd11..a3ee65ec 100644 --- a/components/myportal/watchedcases.js +++ b/components/myportal/watchedcases.js @@ -31,6 +31,7 @@ const WatchedCases = (props) => { currentView={props.currentView} myReps={props.myReps} props={props} + accountDetails={props.accountDetails} />
    @@ -40,12 +41,11 @@ const WatchedCases = (props) => {
    { diff --git a/components/representation.js b/components/representation.js index 418f80ac..77ebb8c7 100644 --- a/components/representation.js +++ b/components/representation.js @@ -22,6 +22,7 @@ const CaseRepresentation = (props) => { watchedCases={props.watchedCases} awaitingSubmission={props.awaitingSubmission} caseReference={props.caseReference} + ticketnumber={props.ticketnumber} currentType={props.currentType} searchResultsObj={props.searchResultsObj} searchDetailsObj={props.searchDetailsObj} diff --git a/components/search/addresssearchresults.js b/components/search/addresssearchresults.js index 097606a3..90b43527 100644 --- a/components/search/addresssearchresults.js +++ b/components/search/addresssearchresults.js @@ -311,8 +311,8 @@ const SearchResults = (props) => { resultsArrPaged.map((item, key) => { let detailsObj = jsonpath({ path: - '$..value[?(@ && @.pinswg_name=="' + - item.pinswg_name + + '$..value[?(@ && @.ticketnumber=="' + + item.ticketnumber + '")]', json: searchDetailsObj, diff --git a/components/search/dnssearchresults.js b/components/search/dnssearchresults.js index 104ad1a1..68500ec5 100644 --- a/components/search/dnssearchresults.js +++ b/components/search/dnssearchresults.js @@ -32,6 +32,7 @@ import { setWatchedCasesDetails, } from "../../store/watchedCases/action"; import { getDetailsProxy, getSearchDetailsPaged } from "../utils"; +import { signIn, useSession } from "next-auth/react"; const DNSSearchResults = (props) => { const { @@ -48,11 +49,13 @@ const DNSSearchResults = (props) => { setWatchedCases, setWatchedCasesDetails, showMap, + showLoginCheck, } = props; let { t } = useTranslation(); const router = useRouter(); const { locale } = router; + const { data: session } = useSession(); var resultsArr = searchResultsObj.value || []; @@ -378,8 +381,8 @@ const DNSSearchResults = (props) => { resultsArr.map((item, key) => { let detailsObj = jsonpath({ path: - '$..value[?(@ && @.pinswg_name=="' + - item.title + + '$..value[?(@ && @.ticketnumber=="' + + item.ticketnumber + '")]', json: searchDetailsObj, eval: true, @@ -443,6 +446,8 @@ const DNSSearchResults = (props) => { "appealType": item.pinswg_appealcasetype, "showMap": showMap, + "showLoginCheck": + props.showLoginCheck, }); }} > @@ -744,6 +749,51 @@ const DNSSearchResults = (props) => { )} )} + + {(showLoginCheck == "true" || + showLoginCheck == true) && + !session && ( +
    + + {t( + "case:watch-this-case-link" + )} + + +
    + )}
    ); }) diff --git a/components/search/searchresults.js b/components/search/searchresults.js index 95f9b683..198ec13e 100644 --- a/components/search/searchresults.js +++ b/components/search/searchresults.js @@ -331,8 +331,8 @@ const SearchResults = (props) => { resultsArr.map((item, key) => { let detailsObj = jsonpath({ path: - '$..value[?(@ && @.pinswg_name=="' + - item.title + + '$..value[?(@ && @.ticketnumber=="' + + item.ticketnumber + '")]', json: searchDetailsObj, eval: true, diff --git a/components/servicebanner.js b/components/servicebanner.js index 5f7ccfdc..324c82ee 100644 --- a/components/servicebanner.js +++ b/components/servicebanner.js @@ -18,7 +18,11 @@ export default function ServiceBanner(props) {

    { 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 + "')]", diff --git a/data/collections.json b/data/collections.json index 64358d07..9073ccfa 100644 --- a/data/collections.json +++ b/data/collections.json @@ -378,7 +378,7 @@ "UrlName": "sips", "MetadataId": "8d31911b-b8ea-ef11-ab08-00224800be9c", "appealTypeID": "846040002", - "NavigationProperty": "pinswg_SIPSIds", + "NavigationProperty": "pinswg_sipscase", "value": "SIP" } ] diff --git a/locales/cy/case.json b/locales/cy/case.json index 6a06de93..40f96591 100644 --- a/locales/cy/case.json +++ b/locales/cy/case.json @@ -109,6 +109,7 @@ "trying-to-watch-case-redirect-label": "Fe'ch anogir nawr i fewngofnodi", "you-have-stopped-watching-label": "Ydych chi am roi'r gorau i wylio achos ", "do-you-want-to-delete-case-label": "Ydych chi am ddileu achos", + "do-you-want-to-delete-rep-label": "Ydych chi eisiau dileu cynrychiolaeth sy'n aros i'w chyflwyno", "do-you-want-to-delete-case-disclaimer-label": "Ar ôl dileu, bydd yr holl wybodaeth a gyflwynwyd gennych yn cael ei cholli.", "representation-date-passed-label": "Mae'r cyfnod cyflwyno sylwadau ar gyfer yr apêl hon rhwng {{startDate}} a {{endDate}}", "representation-date-passed-additional-label": "Gallwch wneud sylw drwy e-bostio,", diff --git a/locales/cy/home.json b/locales/cy/home.json index e6742f8d..1b42ce43 100644 --- a/locales/cy/home.json +++ b/locales/cy/home.json @@ -1,8 +1,8 @@ { - "login-card-title-temp": "Apeliadau neu geisiadau newydd", - "login-comingsoon-temp-1": "Mae'r gwasanaeth hwn yn cael ei ddatblygu i gefnogi apeliadau a cheisiadau ar-lein.", + "login-card-title-temp": "Cyflwyno apêl newydd", + "login-comingsoon-temp-1": "yn erbyn gwrthodiad eich Awdurdod Cynllunio Lleol i roi caniatâd cynllunio neu fethiant i benderfynu ar gais cynllunio mewn pryd.", "login-comingsoon-temp-1a": "Ar hyn o bryd, gallwch gyflwyno Apeliadau Cynllunio a78, Apeliadau Cydsyniad Adeilad Rhestredig ac Ardal Gadwraeth, Apeliadau Deiliaid Tai a Mân Apeliadau Masnachol - HAS/CAS, Apeliadau Hysbysebion a Barnu'n Annilys.", - "login-comingsoon-temp-2": "Wrth i ni ddatblygu’r gwasanaeth ar-lein, dewch o hyd i:", + "login-comingsoon-temp-2": "Mae'r gwasanaeth hwn ar agor ar hyn o bryd i gyflwyno apeliadau newydd yn erbyn gwrthod caniatâd cynllunio neu fethu â phenderfynu ar gais cynllunio mewn pryd (apeliadau adran 78). Mae'r gwasanaeth yn cael ei ddatblygu i gefnogi apeliadau a cheisiadau ar-lein eraill. Yn y cyfamser, gallwch ddod o hyd i'r ffurflenni yma", "login-comingsoon-forms-link-1": "https://llyw.cymru/ffurflenni-apelio", "login-comingsoon-forms-label-1": "ffurflenni apêl cynllunio a ffurflenni cais cynllunio", "login-comingsoon-forms-link-2": "https://llyw.cymru/trwyddedau-amgylcheddol", @@ -32,9 +32,9 @@ "casesearch-card-advanced-link": "Chwiliad uwch", "casesearch-search-validation-required": "Angenrheidiol", "casesearch-search-validation-minlength": "Rhaid iddo gynnwys 4 nod neu fwy", - "casescomment-card-title": "Rhowch sylwadau ar apêl", - "casescomment-card-paragraph-one": "Rhowch sylwadau ar apêl (ac eithrio apêl deiliaid tai neu fasnachol) drwy e-bostio ", - "casescomment-card-paragraph-two": "Ni all partïon â buddiant wneud sylwadau ar apeliadau deiliaid tai a masnachol yn ystod y cam apelio. Bydd unrhyw sylwadau a wnaed yn ystod y cam ymgeisio yn cael eu darparu gan yr awdurdod cynllunio lleol a'u hystyried gan yr Arolygydd.", + "casescomment-card-title": "Sylwadau ar apeliadau neu geisiadau", + "casescomment-card-paragraph-one": "Fel arall, gallwch ofyn am ffurflenni neu wneud sylwadau ar apêl yn ystod y cyfnod cynrychioliadau drwy e-bostio ", + "casescomment-card-paragraph-two": "yn ystod y cyfnod cynrychioliadau neu gyflwyno datganiadau achos. Cyfeiriwch at y dyddiadau cau penodol i'r achos. Ar gyfer apeliadau deiliaid tai a masnachol, ni all partïon â diddordeb wneud sylwadau yn ystod y cam apelio. Bydd unrhyw sylwadau a wneir yn ystod y cam ymgeisio yn cael eu darparu gan yr Awdurdod Cynllunio Lleol a'u hystyried gan yr Arolygydd.", "inspectorate-card-visit-label": "Ymweld â'r Arolygiaeth Gynllunio", "inspectorate-card-visit-link": "Hafan", "inspectorate-card-alt-text": "Yr Arolygiaeth Gynllunio", @@ -48,9 +48,9 @@ "completed-uploading-files-label": "{{number}} ffeil wedi'u huwchlwytho", "remove-this-file-label": "Tynnu'r ffeil hon", "watch-case-card-title": "Gwylio achos", - "watch-case-paragraph-one": "Os oes gennych ddiddordeb mewn achos, dewiswch ei wylio o'ch dangosfwrdd.", + "watch-case-paragraph-one": "i gadw golwg ar y camau nesaf a chanlyniad yr apêl.", "casescomment-card-paragraph-three": "Gallwch wneud sylwadau ar apeliadau a cheisiadau yn ystod y cyfnod cynrychioli neu gyflwyno datganiadau achos neu'r Holiadur LPA.", "casescomment-card-paragraph-four": "Cyfeiriwch at y dyddiadau cau ar gyfer cynrychioli achosion unigol ar gyfer datganiadau a sylwadau.", - "signin-benefits-title": "Buddion mewngofnodi", - "signin-benefits-paragraph": "Mae cofrestru ar y porth Gwaith Achos Cynllunio yn caniatáu ichi:" + "signin-benefits-title": "Mewngofnodwch i'ch porth", + "signin-benefits-paragraph": "Drwy fewngofnodi gyda'r botwm Mewngofnodi, byddwch yn gallu:" } \ No newline at end of file diff --git a/locales/cy/search.json b/locales/cy/search.json index e8a3c972..d2b13ce2 100644 --- a/locales/cy/search.json +++ b/locales/cy/search.json @@ -67,5 +67,7 @@ "searchresults-show-records-label-a": "Dangos", "searchresults-show-records-label-b": "cofnodion", "searchresults-created-on-label": "Crëwyd ar", - "address-search-appellant-validation": "Mae angen rhan o'r cyfeiriad i chwilio gydag enw" + "address-search-appellant-validation": "Mae angen rhan o'r cyfeiriad i chwilio gydag enw", + "filter-documents-label": "Hidlo dogfennau", + "clear-filter-button-label": "Clirio'r hidlydd" } \ No newline at end of file diff --git a/locales/en/case.json b/locales/en/case.json index c7cd77d2..cd412589 100644 --- a/locales/en/case.json +++ b/locales/en/case.json @@ -110,6 +110,7 @@ "trying-to-watch-case-redirect-label": "You will now be prompted to sign in", "you-have-stopped-watching-label": "Do you want to stop watching case ", "do-you-want-to-delete-case-label": "Do you want to delete case ", + "do-you-want-to-delete-rep-label": "Do you want to delete representation awaiting submission", "do-you-want-to-delete-case-disclaimer-label": "Once deleted all information you have submited, will be lost.", "representation-date-passed-label": "The representation period for this appeal is between {{startDate}} and {{endDate}}", "representation-date-passed-additional-label": "You can make a representation by emailing,", diff --git a/locales/en/home.json b/locales/en/home.json index a83f95e1..621b6e93 100644 --- a/locales/en/home.json +++ b/locales/en/home.json @@ -2,7 +2,7 @@ "login-card-title-temp": "Submit a new appeal", "login-comingsoon-temp-1": "This service is being developed to support online appeals and applications. You can currently raise planning appeals.", "login-comingsoon-temp-1a": "You can currently raise Planning Appeals s78.", - "login-comingsoon-temp-2": "While we develop the online service, find:", + "login-comingsoon-temp-2": "This service is currently open to submit new appeals against refusal of planning permission or failure to determine a planning application in time (section 78 appeals). The service is being developed to support other online appeals and applications. In the meantime, you can find the forms here", "login-comingsoon-forms-link-1": "https://gov.wales/planning-appeal-forms", "login-comingsoon-forms-label-1": "planning appeal and application forms", "login-comingsoon-forms-link-2": "https://gov.wales/environmental-permits", @@ -32,9 +32,9 @@ "casesearch-card-advanced-link": "Advanced search", "casesearch-search-validation-required": "Required", "casesearch-search-validation-minlength": "Must be 4 characters or more", - "casescomment-card-title": "Comment on an appeal or application", - "casescomment-card-paragraph-one": "Alternatively you can comment on an appeal (excluding householder or commercial) by emailing ", - "casescomment-card-paragraph-two": "For householder and commercial appeals, interested parties are unable to comment at appeal stage. Any comments made at application stage will be provided by the Local Planning Authority and considered by the inspector.", + "casescomment-card-title": "Comment on appeals or applications", + "casescomment-card-paragraph-one": "Alternatively, you can request forms or comment on an appeal during the representation period by emailing ", + "casescomment-card-paragraph-two": "during the representation period or submit statements of case. Please refer to the case specific deadlines. For householder and commercial appeals, interested parties are unable to comment at appeal stage. Any comments made at application stage will be provided by the Local Planning Authority and considered by the Inspector.", "inspectorate-card-visit-label": "Visit the Planning Inspectorate", "inspectorate-card-visit-link": "Home", "inspectorate-card-alt-text": "The Planning Inspectorate", @@ -48,9 +48,9 @@ "completed-uploading-files-label": "{{number}} files uploaded", "remove-this-file-label": "Remove this file", "watch-case-card-title": "Watch a case", - "watch-case-paragraph-one": "If you are interested in a case you can select to watch it from your dashboard.", + "watch-case-paragraph-one": "to keep track of the next steps and outcome of the appeal.", "casescomment-card-paragraph-three": "You can make comments on appeals and applications during the representation period or submit statements of case or the LPA Questionnaire.", "casescomment-card-paragraph-four": "Please refer to the individual case representation deadlines for statements and comments.", - "signin-benefits-title": "Sign in benefits", - "signin-benefits-paragraph": "Registering on the Planning Casework portal allows you to:" + "signin-benefits-title": "Sign in to your portal", + "signin-benefits-paragraph": "By signing in with the Sign in button, you will be able to:" } \ No newline at end of file diff --git a/locales/en/search.json b/locales/en/search.json index 0dc2d533..93d9fa3c 100644 --- a/locales/en/search.json +++ b/locales/en/search.json @@ -67,5 +67,7 @@ "searchresults-show-records-label-a": "Show", "searchresults-show-records-label-b": "records", "searchresults-created-on-label": "Created on", - "address-search-appellant-validation": "Need part of the address to search with a name" + "address-search-appellant-validation": "Need part of the address to search with a name", + "filter-documents-label": "Filter documents", + "clear-filter-button-label": "Clear filter" } \ No newline at end of file diff --git a/next-env.d.ts b/next-env.d.ts index fd36f949..a4a7b3f5 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/pages/api/endpoint/getappealtypes_api.js b/pages/api/endpoint/getappealtypes_api.js index a206cb59..596defca 100644 --- a/pages/api/endpoint/getappealtypes_api.js +++ b/pages/api/endpoint/getappealtypes_api.js @@ -37,7 +37,7 @@ export default async function ApiProxy(req, res) { var queryUrl = "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' " + (process.env.SHOWSIPS !== "true" - ? "and pinswg_appealcasetype ne 846040002" + ? "and attributevalue ne 846040002" : "") + "&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; @@ -47,7 +47,7 @@ export default async function ApiProxy(req, res) { // "stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; //"stringmaps?$filter=objecttypecode eq 'incident' and attributename eq 'pinswg_appealcasetype' and value ne 'Developments of National Significance' and value ne 'LDP' and value ne 'Misc Casework'&$count=true&$select=value,stringmapid,organizationid,attributevalue&$orderby=value asc"; - //console.log(queryUrl); + console.log(queryUrl); return axios .get( diff --git a/pages/api/endpoint/getbasicsearch_api.js b/pages/api/endpoint/getbasicsearch_api.js index 8b8a3e2b..763f0447 100644 --- a/pages/api/endpoint/getbasicsearch_api.js +++ b/pages/api/endpoint/getbasicsearch_api.js @@ -51,7 +51,7 @@ export default async function ApiProxy(req, res) { searchString + "')) and pinswg_appealcasetype ne null " + (process.env.SHOWSIPS !== "true" - ? "and pinswg_appealcasetype ne 846040002" + ? "and pinswg_appealcasetype ne 846040002 " : "") + "and pinswg_publishtoweb eq true&$orderby=createdon desc&$count=true"; diff --git a/pages/api/endpoint/getbasicsearch_by_address_api.js b/pages/api/endpoint/getbasicsearch_by_address_api.js index 2005d723..eae961db 100644 --- a/pages/api/endpoint/getbasicsearch_by_address_api.js +++ b/pages/api/endpoint/getbasicsearch_by_address_api.js @@ -306,7 +306,7 @@ export default async function ApiProxy(req, res) { "MetadataId": "8d31911b-b8ea-ef11-ab08-00224800be9c", "appealTypeID": "846040002", "tmpNav": "pinswg_sipsid", - "NavigationProperty": "pinswg_SIPSids", + "NavigationProperty": "pinswg_sipscase", "value": "SIP", }, diff --git a/pages/api/endpoint/getbasicsearchdetails_api.js b/pages/api/endpoint/getbasicsearchdetails_api.js index 049425be..16556c05 100644 --- a/pages/api/endpoint/getbasicsearchdetails_api.js +++ b/pages/api/endpoint/getbasicsearchdetails_api.js @@ -33,7 +33,7 @@ import axios from "axios"; import CryptoJS from "crypto-js"; import { azureHeaders, consoleLogger, getToken } from "../../../actions"; import { getSelectQuery } from "../../../actions/selectQueryTypes"; - +import { getNavigationPropertyByPrimaryAttribute } from "../../../components/utils"; const WORDKEY = process.env.HASHKEY; const WEBAPI_URL = @@ -55,6 +55,11 @@ export default async function ApiProxy(req, res) { var incidentID = req.query.incidentID; var token = await getToken(); + let navigationProperty = + getNavigationPropertyByPrimaryAttribute( + primaryIdAttribute + ).NavigationProperty; + var queryUrl = appealTypeName + "?$filter=_" + @@ -63,7 +68,11 @@ export default async function ApiProxy(req, res) { : primaryIdAttribute + "s_value ") + " eq " + incidentID + - "&$count=true"; + "&$count=true" + + "&$expand=" + + navigationProperty + + "($select=ticketnumber)"; + //" and statuscode eq 1&$count=true"; // queryUrl = @@ -91,6 +100,13 @@ export default async function ApiProxy(req, res) { azureHeaders(token.access_token) ) .then(({ data }) => { + let flattened = data.value.map((r) => ({ + ...r, + ticketnumber: r[navigationProperty]?.ticketnumber || null, + })); + + data.value = flattened; + res.status(200).json(data); }) .catch((error) => { diff --git a/pages/api/endpoint/getbasicsearchdetailspaged_api.js b/pages/api/endpoint/getbasicsearchdetailspaged_api.js index 2929a751..1d841bab 100644 --- a/pages/api/endpoint/getbasicsearchdetailspaged_api.js +++ b/pages/api/endpoint/getbasicsearchdetailspaged_api.js @@ -34,7 +34,7 @@ import CryptoJS from "crypto-js"; import _ from "lodash"; import { azureHeadersPaged, consoleLogger, getToken } from "../../../actions"; import { getSelectQuery } from "../../../actions/selectQueryTypes"; - +import { getNavigationPropertyByPrimaryAttribute } from "../../../components/utils"; const WORDKEY = process.env.HASHKEY; const WEBAPI_URL = @@ -59,6 +59,11 @@ export default async function ApiProxy(req, res) { var incidentID = req.query.incidentID; var token = await getToken(); + let navigationProperty = + getNavigationPropertyByPrimaryAttribute( + primaryIdAttribute + ).NavigationProperty; + var queryUrl = appealTypeName + "?$filter=_" + @@ -67,7 +72,11 @@ export default async function ApiProxy(req, res) { : primaryIdAttribute + "s_value ") + " eq " + incidentID + - "&$count=true"; + "&$count=true" + + "&$expand=" + + navigationProperty + + "($select=ticketnumber)"; + //" and statuscode eq 1&$count=true"; queryUrl = @@ -86,10 +95,18 @@ export default async function ApiProxy(req, res) { azureHeadersPaged(token.access_token) ) .then(({ data }) => { + let flattened = data.value.map((r) => ({ + ...r, + ticketnumber: r[navigationProperty]?.ticketnumber || null, + })); + + data.value = flattened; + var dataStr; _.has(data, "@odata.nextLink") == true && ((dataStr = JSON.stringify(data["@odata.nextLink"])), (data["@odata.nextLink"] = dataStr.split("/v8.2/")[1])); + return res.status(200).json(data); }) .catch((error) => { diff --git a/pages/api/endpoint/getbasicsearchpaged_api.js b/pages/api/endpoint/getbasicsearchpaged_api.js index c8e265fa..95cfc671 100644 --- a/pages/api/endpoint/getbasicsearchpaged_api.js +++ b/pages/api/endpoint/getbasicsearchpaged_api.js @@ -85,7 +85,7 @@ export default async function ApiProxy(req, res) { searchString + "')) and pinswg_appealcasetype ne null " + (process.env.SHOWSIPS !== "true" - ? "and pinswg_appealcasetype ne 846040002" + ? "and pinswg_appealcasetype ne 846040002 " : "") + "and pinswg_publishtoweb eq true&$orderby=" + orderby + diff --git a/pages/api/endpoint/getwatchedcasesproxy_api.js b/pages/api/endpoint/getwatchedcasesproxy_api.js index e3159cd1..116d96b1 100644 --- a/pages/api/endpoint/getwatchedcasesproxy_api.js +++ b/pages/api/endpoint/getwatchedcasesproxy_api.js @@ -48,7 +48,9 @@ export default async function ApiProxy(req, res) { // "&$select=pinswg_emailnotifications,modifiedon,pinswg_appealcasetype,pinswg_watchlistid,_pinswg_watchedcase_value,statuscode,pinswg_representationsubmitted,pinswg_representationtype&$count=true&$orderby=createdon desc&$expand=pinswg_WatchedCase($select=pinswg_AssociatedLPA)"; var queryUrl = - "/api/endpoint/getwatchedcases_api?loggedInUserId=" + loggedInUserId; + "pinswg_watchlists?$filter= _pinswg_contact_value eq " + + loggedInUserId + + "&$select=modifiedon,pinswg_appealcasetype,pinswg_watchlistid,_pinswg_watchedcase_value,statuscode,pinswg_representationsubmitted,pinswg_representationtype&$count=true&$orderby=createdon desc&$expand=pinswg_WatchedCase($select=pinswg_AssociatedLPA)"; return axios .get( @@ -56,32 +58,33 @@ export default async function ApiProxy(req, res) { azureHeaders(token.access_token) ) .then(({ data }) => { - // data.value.forEach(function (element) { - // element.ticketnumber = element.pinswg_WatchedCase?.ticketnumber; - // element.pinswg_title = - // element[ - // "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue" - // ]; + data.value.forEach(function (element) { + element.ticketnumber = element.pinswg_WatchedCase.ticketnumber; + element.pinswg_title = + element[ + "_pinswg_watchedcase_value@OData.Community.Display.V1.FormattedValue" + ]; - // element[ - // "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue" - // ] = - // element.pinswg_WatchedCase?.[ - // "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue" - // ]; - // element._pinswg_associatedlpa_value = - // element.pinswg_WatchedCase?._pinswg_associatedlpa_value; - // element[ - // "_ownerid_value@OData.Community.Display.V1.FormattedValue" - // ] = - // element.pinswg_WatchedCase?.[ - // "_ownerid_value@OData.Community.Display.V1.FormattedValue" - // ]; - // element._ownerid_value = - // element.pinswg_WatchedCase?._ownerid_value; + element[ + "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue" + ] = + element.pinswg_WatchedCase[ + "_pinswg_associatedlpa_value@OData.Community.Display.V1.FormattedValue" + ]; + element._pinswg_associatedlpa_value = + element.pinswg_WatchedCase._pinswg_associatedlpa_value; + element[ + "_ownerid_value@OData.Community.Display.V1.FormattedValue" + ] = + element.pinswg_WatchedCase[ + "_ownerid_value@OData.Community.Display.V1.FormattedValue" + ]; + element._ownerid_value = + element.pinswg_WatchedCase._ownerid_value; + + delete element.pinswg_WatchedCase; + }); - // delete element.pinswg_WatchedCase; - // }); res.status(200).json(data); }) .catch((error) => { diff --git a/pages/api/file/downloadblob.js b/pages/api/file/downloadblob.js index 6067189a..5ad78d18 100644 --- a/pages/api/file/downloadblob.js +++ b/pages/api/file/downloadblob.js @@ -24,10 +24,19 @@ ApiProxy.get(async (req, res) => { "&blobname=" + blobName.trim(); + // console.log(checkquerypath); + + // console.log(hashAPIPath(checkquerypath)); + + // console.log(req.query); + if (hashAPIPath(checkquerypath) == "&hash=" + checkHash) { + const bloblocation = + casefolderID + (blobName.indexOf(".json") > 0 ? "/" : "/files/"); + const downloaded = await downloadFile( containerName, - casefolderID + "/files/" + decodeURI(blobName) + bloblocation + decodeURI(blobName) ); res.setHeader( diff --git a/pages/api/file/editRepJson.js b/pages/api/file/editRepJson.js new file mode 100644 index 00000000..65080769 --- /dev/null +++ b/pages/api/file/editRepJson.js @@ -0,0 +1,83 @@ +import { DefaultAzureCredential } from "@azure/identity"; +import { BlobServiceClient } from "@azure/storage-blob"; + +export default async function handler(req, res) { + if (req.method !== "POST") { + res.status(405).json({ error: "Method not allowed" }); + return; + } + + const { container, blobName } = req.body; + + if (!container || !blobName) { + res.status(400).json({ error: "Missing container or blobName" }); + return; + } + + try { + const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME; + const creds = new DefaultAzureCredential(); + const blobServiceClient = new BlobServiceClient( + `https://${accountName}.blob.core.windows.net`, + creds + ); + + const containerClient = blobServiceClient.getContainerClient(container); + const blockBlobClient = containerClient.getBlockBlobClient(blobName); + + // Download blob content + const downloadResponse = await blockBlobClient.download(0); + const downloaded = await streamToString( + downloadResponse.readableStreamBody + ); + + // Parse JSON + const json = JSON.parse(downloaded); + + // Remove repComplete element if it exists + if ("repComplete" in json) { + delete json.repComplete; + } + + const tags = { + containerid: json.containerID, + caseID: json.ticketnumber, + blobType: "Representation", + }; + + // Convert back to string + const updatedContent = JSON.stringify(json, null, 2); + + // Upload updated content (overwrite) + await blockBlobClient.upload( + updatedContent, + Buffer.byteLength(updatedContent), + { + blobHTTPHeaders: { blobContentType: "application/json" }, + } + ); + + console.log("the tags:", tags); + const withTags = await blockBlobClient.setTags(tags); + const withMeta = await blockBlobClient.setMetadata(tags); + + res.status(200).json({ message: "repComplete removed successfully" }); + } catch (error) { + console.error("Error editing rep.json:", error); + res.status(500).json({ error: "Failed to edit rep.json" }); + } +} + +// Helper function to read stream to string +async function streamToString(readableStream) { + return new Promise((resolve, reject) => { + const chunks = []; + readableStream.on("data", (data) => { + chunks.push(data.toString()); + }); + readableStream.on("end", () => { + resolve(chunks.join("")); + }); + readableStream.on("error", reject); + }); +} diff --git a/pages/api/file/generatepdf.js b/pages/api/file/generatepdf.js index 4e5e0055..d274d013 100644 --- a/pages/api/file/generatepdf.js +++ b/pages/api/file/generatepdf.js @@ -166,7 +166,7 @@ export default async function handler(req, res) { var containerID = reqBodyobj.containerID; var casefolderID = reqBodyobj.casefolderID; - var caseRef = reqBodyobj.caseRef; + var caseRef = reqBodyobj.ticketnumber; var representationType = reqBodyobj.representationType; var repRaiser = reqBodyobj.lastname; var localeSelect = reqBodyobj.locale; diff --git a/pages/auth/signin2.js b/pages/auth/signin2.js index 0e14448a..569281e7 100644 --- a/pages/auth/signin2.js +++ b/pages/auth/signin2.js @@ -207,6 +207,35 @@ const SignIn = (props) => { }; export async function getServerSideProps(context) { + const { query, req, res } = context; + + // Load allowed IPs from env and trim spaces + const ALLOWED_IPS = process.env.ALLOWED_IPS + ? process.env.ALLOWED_IPS.split(",").map((ip) => ip.trim()) + : []; + + // Always allow localhost addresses + const LOCALHOST_IPS = ["127.0.0.1", "::1"]; + + // Get IP address from headers or socket + const forwarded = req.headers["x-forwarded-for"]; + const ip = + typeof forwarded === "string" + ? forwarded.split(",")[0] + : req.socket.remoteAddress; + + console.log("Visitor IP:", ip); + + // Check whitelist + localhost + if (![...ALLOWED_IPS, ...LOCALHOST_IPS].includes(ip)) { + return { + redirect: { + destination: "/403", // custom "Access Denied" page + permanent: false, + }, + }; + } + if (process.env.SHOWLOGIN == false) { return { redirect: { diff --git a/pages/case/[ticketnumber].js b/pages/case/[ticketnumber].js index 4ae0dc9d..85d30e91 100644 --- a/pages/case/[ticketnumber].js +++ b/pages/case/[ticketnumber].js @@ -85,6 +85,13 @@ const CaseHome = (props) => { props.searchResultsObj.searchResultsObj.value[0] .ticketnumber } + ticketnumber={ + props.currentView.caseReference.ticketnumber + } + ticketnumber={ + props.searchResultsObj.searchResultsObj.value[0] + .ticketnumber + } currentType={props.currentType} appealTypeID={ props.searchResultsObj.searchResultsObj.value[0] diff --git a/pages/dns/[developmentName].js b/pages/dns/[developmentName].js index 97c78311..320b7485 100644 --- a/pages/dns/[developmentName].js +++ b/pages/dns/[developmentName].js @@ -46,7 +46,9 @@ const CaseHome = (props) => { Reference:{" "} - {props.currentView.caseReference.currentReference}{" "} + {props.currentView.caseReference.currentReference || + props.searchResultsObj.searchResultsObj.value[0] + .title}{" "} Developments of National Significance @@ -81,9 +83,16 @@ const CaseHome = (props) => { props.awaitingSubmission.awaitingSubmission } caseReference={ + props.searchResultsObj.searchResultsObj.value[0] + .caseReference + } + ticketnumber={ props.searchResultsObj.searchResultsObj.value[0] .ticketnumber } + // ticketnumber={ + // props.currentView.caseReference.ticketnumber + // } currentType={props.currentType} appealTypeID={ props.searchResultsObj.searchResultsObj.value[0] diff --git a/pages/dnsapplications.js b/pages/dnsapplications.js index b3315c4e..eb859939 100644 --- a/pages/dnsapplications.js +++ b/pages/dnsapplications.js @@ -20,7 +20,7 @@ import { wrapper } from "../store/store"; import ServiceBanner from "../components/servicebanner"; const Home = (props) => { - const { footerLinks, pages, showMap } = props; + const { footerLinks, pages, showMap, showLoginCheck } = props; let { t, lang } = useTranslation(); const router = useRouter(); @@ -105,6 +105,7 @@ const Home = (props) => { showMap={showMap} searchString="DNS" searchResultsObj={props.searchResultsObj} + showLoginCheck={showLoginCheck} />

    + ); +} + +export async function getServerSideProps({ req }) { + // Load allowed IPs from env and trim spaces + const ALLOWED_IPS = process.env.ALLOWED_IPS + ? process.env.ALLOWED_IPS.split(",").map((ip) => ip.trim()) + : []; + + // Always allow localhost addresses + const LOCALHOST_IPS = ["127.0.0.1", "::1"]; + + // Get IP address from headers or socket + const forwarded = req.headers["x-forwarded-for"]; + const ip = + typeof forwarded === "string" + ? forwarded.split(",")[0] + : req.socket.remoteAddress; + + console.log("Visitor IP:", ip); + + // Check whitelist + localhost + if (![...ALLOWED_IPS, ...LOCALHOST_IPS].includes(ip)) { + return { + redirect: { + destination: "/403", // custom "Access Denied" page + permanent: false, + }, + }; + } + const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME; + + const creds = new DefaultAzureCredential(); + + const globalForPrisma = global; + + const prisma = globalForPrisma.prisma || new PrismaClient(); + + const blobServiceClient = new BlobServiceClient( + `https://${accountName}.blob.core.windows.net`, + creds + ); + + const users = await prisma.user.findMany(); + + const hashAPIPath = (queryPath, WORDKEY) => { + var hashlink = CryptoJS.HmacSHA256( + queryPath, + CryptoJS.enc.Hex.parse(WORDKEY) + ); + hashlink = hashlink.toString(CryptoJS.enc.Hex); + return hashlink; + }; + + let data = await Promise.all( + users.map(async (user) => { + const containers = await listContainersForUser( + blobServiceClient, + `${user.id}`, + user.email + ); + + const containersWithHashes = await Promise.all( + containers.map(async (container) => { + const groupedByFolder = await container.blobs.reduce( + async (accP, blob) => { + // Because we'll do async read, reduce needs to be async, so accP is a Promise + const acc = await accP; + + const folderPath = + getUpToLastSlash(blob.name.trim()) || ""; + + const hashedfilepath = hashAPIPath( + "/api/file/downloadblob?container=" + + container.container + + "&casefolderID=" + + folderPath + + "&blobname=" + + blob.name + .substring( + blob.name.lastIndexOf("/") + 1 + ) + .trim(), + process.env.HASHKEY + ); + + const fileNameOnly = blob.name.substring( + blob.name.lastIndexOf("/") + 1 + ); + const isTmpFile = fileNameOnly.startsWith("TMP-"); + + const blobWithHash = { + ...blob, + hashedfilepath, + isTmpFile, + }; + + let folderGroup = acc.find( + (f) => f.folderPath === folderPath + ); + if (!folderGroup) { + folderGroup = { + folderPath, + blobs: [], + hasRepJson: false, + repJsonBlob: null, + repComplete: false, + hasTmpFile: false, + }; + acc.push(folderGroup); + } + + folderGroup.blobs.push(blobWithHash); + + if (isTmpFile) { + folderGroup.hasTmpFile = true; + } + + // If this blob ends with rep.json, fetch and parse JSON + if (blob.name.toLowerCase().endsWith("rep.json")) { + folderGroup.hasRepJson = true; + folderGroup.repJsonBlob = blobWithHash; + + // Read blob content from Azure Storage + const containerClient = + blobServiceClient.getContainerClient( + container.container + ); + const blockBlobClient = + containerClient.getBlockBlobClient( + blob.name + ); + + try { + const downloadResponse = + await blockBlobClient.download(0); + const downloaded = await streamToString( + downloadResponse.readableStreamBody + ); + + const json = JSON.parse(downloaded); + folderGroup.repComplete = Boolean( + json.repComplete + ); + } catch (err) { + console.error( + "Error reading or parsing rep.json", + err + ); + folderGroup.repComplete = false; + } + } + + return acc; + }, + Promise.resolve([]) + ); + + return { + ...container, + folders: groupedByFolder, + }; + }) + ); + + return containersWithHashes.length > 0 + ? { + id: user.id, + email: user.email, + containers: containersWithHashes, + } + : null; + }) + ); + + let userData = await Promise.all( + users + .filter((user) => user.email && user.email.trim() !== "") + .map(async (user) => ({ + id: user.id, + email: user.email, + created: user.emailVerified?.toLocaleString("en-GB") || "", + })) + ); + + let repCompleteCount = 0; + + data = data.filter(Boolean); + + data.forEach((user) => { + user.containers.forEach((container) => { + container.folders.forEach((folder) => { + if (folder.repComplete === true) { + repCompleteCount++; + } + }); + }); + }); + + return { + props: { + data: data, + userData: userData, + repCompleteCount, + }, + }; +} diff --git a/styles/sass/patterns/_card.scss b/styles/sass/patterns/_card.scss index 11bb1e31..3ce8868d 100644 --- a/styles/sass/patterns/_card.scss +++ b/styles/sass/patterns/_card.scss @@ -84,6 +84,8 @@ html[data-useragent*="MSIE 10.0"] .flex-container { font-size: 1.17rem; } + + .card-body { //border-bottom: 1px solid $govuk-border-colour; //$panel-colour; padding: 40px 20px; @@ -327,4 +329,16 @@ div.cardModuleItem:last-of-type { // box-shadow: 0 2px 0 #0b0c0c; } } +} + + +.card { + .cardList-nobullet { + list-style-type: none; + padding-left: 20px; + + li { + margin-bottom: 10px; + } + } } \ No newline at end of file diff --git a/styles/sass/welshgov/_application.scss b/styles/sass/welshgov/_application.scss index 773e064e..8c1f1b98 100644 --- a/styles/sass/welshgov/_application.scss +++ b/styles/sass/welshgov/_application.scss @@ -300,6 +300,17 @@ a.longLinkBreak { } @media screen and (max-width: 670px) { + img { + + &.serviceTitle { + width: 236px; + + &.cy { + width: 238px; + } + } + } + flex-direction: column-reverse; align-items: flex-start; @@ -1506,6 +1517,14 @@ textarea, .govuk-summary-list__key { width: 45%; } + + +} + +#login-card { + .heading-small { + font-size: 1rem; + } } .react-datepicker__input-container input { @@ -2576,6 +2595,45 @@ dd.govuk-summary-list__value.govuk-\!-font-size-14.govuk-summary-list__action { + & .cardModuleRemoveCase { + border: 1px solid $red; + padding: 5px; + height: 20px; + padding-top: 0px; + padding-bottom: 0px; + border-radius: 5px; + width: auto; + color: white !important; + font-weight: bold; + background-color: $red; + font-size: 15px; + cursor: pointer; + + &:active { + top: 2px; + } + + &:hover { + background-color: $lightred; + color: $white !important; + text-decoration: none; + } + + &:focus { + border-color: #ffdd00; + outline: 3px solid transparent; + -webkit-box-shadow: inset 0 0 0 1px #ffdd00; + box-shadow: inset 0 0 0 1px #ffdd00; + } + + &:focus:not(:active):not(:hover) { + border-color: #ffdd00; + color: #0b0c0c; + // background-color: #ffdd00; + // -webkit-box-shadow: 0 2px 0 #0b0c0c; + // box-shadow: 0 2px 0 #0b0c0c; + } + } }