Merged PR 1334: file upload and UAT fixes

Related work items: #12956
This commit is contained in:
Robert Bond
2024-12-11 11:29:18 +00:00
10 changed files with 507 additions and 383 deletions
+18
View File
@@ -1686,6 +1686,24 @@ export const getFilesFromBlob = (containerName, casefolderID) => {
}); });
}; };
export const getFilesFromBlobproxy = (containerName, casefolderID) => {
return axios
.get(
BASE_URL +
"/api/file/getbloblistproxy?container=" +
containerName +
"&casefolderID=" +
casefolderID
)
.then((res) => {
//console.log("//////////----", res.data);
return res.data;
})
.catch((error) => {
consoleLogger(error);
});
};
export const getFilesFromBlobHashed = ( export const getFilesFromBlobHashed = (
containerName, containerName,
getblobshash, getblobshash,
+84 -19
View File
@@ -14,6 +14,7 @@ import {
deleteBlob, deleteBlob,
getFilesFromBlobHashed, getFilesFromBlobHashed,
uploadSingleFile, uploadSingleFile,
getFilesFromBlobproxy,
} from "../../actions"; } from "../../actions";
import fieldLookup from "../../data/crmfieldlookuptranslations.json"; import fieldLookup from "../../data/crmfieldlookuptranslations.json";
import pickListLookup from "../../data/picklistLookups.json"; import pickListLookup from "../../data/picklistLookups.json";
@@ -656,7 +657,9 @@ const RenderDatePicker = ({
</div> </div>
)} )}
</legend> </legend>
{touched && error && ( {!custom.hasOwnProperty("showErrorBottom")
? touched &&
error && (
<span <span
id={id + "-error"} id={id + "-error"}
className="govuk-error-message" className="govuk-error-message"
@@ -666,7 +669,8 @@ const RenderDatePicker = ({
</span>{" "} </span>{" "}
{errorMsg} {errorMsg}
</span> </span>
)} )
: ""}
{/* {value} {/* {value}
<br /> <br />
@@ -693,6 +697,20 @@ const RenderDatePicker = ({
autoComplete="off" autoComplete="off"
//value={!value ? null : moment(value, "DD/MM/yyyy")} //value={!value ? null : moment(value, "DD/MM/yyyy")}
/> />
{custom.hasOwnProperty("showErrorBottom")
? touched &&
error && (
<span
id={id + "-error"}
className="govuk-error-message"
>
<span className="govuk-visually-hidden">
Error:
</span>{" "}
{error}
</span>
)
: ""}
</fieldset> </fieldset>
</div> </div>
</> </>
@@ -1748,6 +1766,7 @@ export function FileUploadField(props) {
containerID={props.containerID} containerID={props.containerID}
uploadCount={props.uploadCount} uploadCount={props.uploadCount}
setFileCount={props.setFileCount} setFileCount={props.setFileCount}
props={props.props}
/> />
</> </>
); );
@@ -2023,8 +2042,54 @@ const RenderFileUpload = (field) => {
field.ticketnumber field.ticketnumber
).then((data) => { ).then((data) => {
console.log(data); console.log(data);
let buildAppealFilesArray = [];
let values = field.form.appealForm.values;
let filesUploadObj = renamedAcceptedFiles;
for (let key in filesUploadObj) {
typeof filesUploadObj[key].name != "undefined" &&
buildAppealFilesArray.push({
"name": filesUploadObj[key].name,
"size": filesUploadObj[key].size,
});
}
//console.log(buildAppealFilesArray);
function removeDuplicates(arr, key) {
const seen = new Set();
return arr.filter((item) => {
const value = item[key];
if (seen.has(value)) {
return false; // Duplicate found
} else {
seen.add(value); // Add value to the set
return true; // Keep the item
}
});
}
buildAppealFilesArray = values.hasOwnProperty(
"filesList"
)
? buildAppealFilesArray.concat(values.filesList)
: buildAppealFilesArray;
buildAppealFilesArray = removeDuplicates(
buildAppealFilesArray,
"name"
);
Object.assign(values, {
"filesList": buildAppealFilesArray,
});
getFilesFromBlobproxy(
field.containerID,
field.ticketnumber
).then((data) => {
field.setFilesForAppeal(data);
setCompletedUploadFiles(true); setCompletedUploadFiles(true);
}); });
});
}} }}
onDropRejected={handleDropRejected} onDropRejected={handleDropRejected}
onDropAccepted={handleDropAccepted} onDropAccepted={handleDropAccepted}
@@ -2057,7 +2122,7 @@ const RenderFileUpload = (field) => {
)} )}
{completedUploadFiles > 0 && ( {completedUploadFiles > 0 && (
<div className="govuk-body govuk-!-font-size-14"> <div className="govuk-body govuk-!-font-size-14">
{uploadCountMessage} files completed{" "} {uploadCountMessage} files uploaded{" "}
</div> </div>
)} )}
</section> </section>
@@ -2076,17 +2141,12 @@ const RenderFileUpload = (field) => {
{field.meta.touched && field.meta.error && ( {field.meta.touched && field.meta.error && (
<span className="error">{field.meta.error}</span> <span className="error">{field.meta.error}</span>
)} )}
{filesList.length > 0 &&
(completedUploadFiles ? (
"Done"
) : (
<p className="govuk-body textloading">Uploading</p>
))}
{files && Array.isArray(files) && ( {files && Array.isArray(files) && (
<> <>
{/* {(files = removeEmptyObjects(files))} */} {/* {(files = removeEmptyObjects(files))} */}
<br />
{files.map( {!completedUploadFiles &&
files.map(
(file, i) => (file, i) =>
typeof file.name != "undefined" && ( typeof file.name != "undefined" && (
<div <div
@@ -2102,13 +2162,16 @@ const RenderFileUpload = (field) => {
&minus; &minus;
</span> </span>
<img <img
src={getThumbnailIcon(file, file.type)} src={getThumbnailIcon(
file,
file.type
)}
alt={file.name} alt={file.name}
width="50" width="50"
/> />
<span className="govuk-body govuk-!-font-size-14 govuk-!-padding-left-5"> <span className="govuk-body govuk-!-font-size-14 govuk-!-padding-left-5">
{file.name} ({bytesToSize(file.size)}){" "} {file.name} (
<br /> {bytesToSize(file.size)}) <br />
<div id={file.name + "_" + i}> <div id={file.name + "_" + i}>
{completedUploadFiles ? ( {completedUploadFiles ? (
<p className="govuk-body govuk-!-font-size-14"> <p className="govuk-body govuk-!-font-size-14">
@@ -2214,15 +2277,15 @@ const RenderSubFields = ({ fields, meta: { touched, error }, ...custom }) => {
return errors; return errors;
}; };
const required = (value) =>
value ? undefined : t("newappeal:is-required-label");
return ( return (
<ul> <ul className="subFieldList">
<div>
{fields.map((member, index) => ( {fields.map((member, index) => (
<div key={index}> <div key={index}>
<h4> <h4>
{subTitle == "owners" ? "Owner" : "Tenant"} # {subTitle == "owners" ? "Owner" : "Tenant"} #{index + 1}
{index + 1}
</h4> </h4>
<div className="fieldArrayContainer"> <div className="fieldArrayContainer">
@@ -2247,7 +2310,9 @@ const RenderSubFields = ({ fields, meta: { touched, error }, ...custom }) => {
label="Date served " label="Date served "
dateStart={"-6m"} dateStart={"-6m"}
dateEnd={"0"} dateEnd={"0"}
validate={[required]}
className="govuk-input govuk-input--width-10" className="govuk-input govuk-input--width-10"
showErrorBottom={true}
/> />
<button <button
@@ -2261,7 +2326,7 @@ const RenderSubFields = ({ fields, meta: { touched, error }, ...custom }) => {
</div> </div>
</div> </div>
))} ))}
</div>
<br /> <br />
{fields.length < custom.maxSubField && ( {fields.length < custom.maxSubField && (
<button <button
+26 -25
View File
@@ -127,11 +127,11 @@ let BuildCheckRow = (props) => {
// ] // ]
// ); // );
if ( // if (
typeof props.props.form["appealForm"].values[ // typeof props.props.form["appealForm"].values[
datafieldname[0].value // datafieldname[0].value
] != "undefined" // ] != "undefined"
) { // ) {
return ( return (
<div className="govuk-summary-list__row" key={key}> <div className="govuk-summary-list__row" key={key}>
<dt className="govuk-summary-list__key"> <dt className="govuk-summary-list__key">
@@ -145,32 +145,33 @@ let BuildCheckRow = (props) => {
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: props.props.form[ __html: props.props.form[
"appealForm" "appealForm"
].values[ ].values[datafieldname[0].value],
datafieldname[0].value
],
}} }}
/> />
) : fieldtype[0].value == ) : fieldtype[0].value ==
"{5B773807-9FB2-42db-97C3-7A91EFF8ADFF}" ? ( "{5B773807-9FB2-42db-97C3-7A91EFF8ADFF}" ? (
formatDate( formatDate(
props.props.form["appealForm"] props.props.form["appealForm"].values[
.values[datafieldname[0].value] datafieldname[0].value
]
) )
) : fieldtype[0].value == ) : fieldtype[0].value ==
"{3EF39988-22BB-4f0b-BBBE-64B5A3748AEE}" ? ( "{3EF39988-22BB-4f0b-BBBE-64B5A3748AEE}" ? (
getPickListLabel( getPickListLabel(
props.props.formData.pickListData, props.props.formData.pickListData,
datafieldname[0].value, datafieldname[0].value,
props.props.form["appealForm"] props.props.form["appealForm"].values[
.values[datafieldname[0].value] datafieldname[0].value
]
) )
) : fieldtype[0].value == ) : fieldtype[0].value ==
"{07FAC785-CD58-4f9f-ABB3-4B7DDC6ED5ED}" ? ( "{07FAC785-CD58-4f9f-ABB3-4B7DDC6ED5ED}" ? (
getRadioLabel( getRadioLabel(
props.props.formData.pickListData, props.props.formData.pickListData,
datafieldname[0].value, datafieldname[0].value,
props.props.form["appealForm"] props.props.form["appealForm"].values[
.values[datafieldname[0].value] datafieldname[0].value
]
) )
) : fieldtype[0].value == ) : fieldtype[0].value ==
"{67FAC785-CD58-4f9f-ABB3-4B7DDC6ED5ED}" ? ( "{67FAC785-CD58-4f9f-ABB3-4B7DDC6ED5ED}" ? (
@@ -207,8 +208,7 @@ let BuildCheckRow = (props) => {
> >
<img <img
style={{ style={{
minWidth: minWidth: "50",
"50",
width: "50", width: "50",
}} }}
src={getThumbnailIconByExtension( src={getThumbnailIconByExtension(
@@ -219,8 +219,7 @@ let BuildCheckRow = (props) => {
/> />
<span <span
style={{ style={{
maxWidth: maxWidth: "85%",
"85%",
}} }}
className="govuk-body govuk-!-font-size-14 govuk-!-margin-left-2" className="govuk-body govuk-!-font-size-14 govuk-!-margin-left-2"
> >
@@ -233,10 +232,11 @@ let BuildCheckRow = (props) => {
)} )}
</div> </div>
))} ))}
<br /> <br />
{typeof props.props.form["appealForm"]
{props.props.form[ .values[datafieldname[0].value] !=
"undefined" &&
props.props.form[
"appealForm" "appealForm"
].values[ ].values[
datafieldname[0].value datafieldname[0].value
@@ -297,6 +297,9 @@ let BuildCheckRow = (props) => {
</> </>
) : fieldtype[0].value == ) : fieldtype[0].value ==
"{0273EDBD-AC1D-40d3-9FB2-095C621B552D}" ? ( "{0273EDBD-AC1D-40d3-9FB2-095C621B552D}" ? (
typeof props.props.form["appealForm"]
.values[datafieldname[0].value] !=
"undefined" &&
props.props.form["appealForm"].values[ props.props.form["appealForm"].values[
datafieldname[0].value datafieldname[0].value
].map((tenant, index) => { ].map((tenant, index) => {
@@ -340,16 +343,14 @@ let BuildCheckRow = (props) => {
{t("newappeal:change-link-label")} {t("newappeal:change-link-label")}
<span className="govuk-visually-hidden"> <span className="govuk-visually-hidden">
{" "} {" "}
{FieldsTranslations( {FieldsTranslations(rows[0].value)}
rows[0].value
)}
</span> </span>
</a> </a>
)} )}
</dd> </dd>
</div> </div>
); );
} // }
} }
})} })}
</> </>
+1 -3
View File
@@ -315,9 +315,7 @@ let BuildCheckSection = (props) => {
<a <a
className="govuk-link" className="govuk-link"
href="#" href="#"
onClick={() => onClick={() => setCurrentSection(sectionCount)}
setCurrentSection(sectionCount - 1)
}
> >
{t("common:back-link")} {t("common:back-link")}
</a> </a>
+1
View File
@@ -217,6 +217,7 @@ export default function BuildField(props) {
uploadCount={props.uploadCount} uploadCount={props.uploadCount}
setFileCount={props.props.setFileCount} setFileCount={props.props.setFileCount}
setUploadCount={props.setUploadCount} setUploadCount={props.setUploadCount}
props={props.props.props.props}
/> />
</div> </div>
); );
+11 -30
View File
@@ -173,10 +173,9 @@ let BuildSection = (props) => {
setSavingStatus(useSaveStatus); setSavingStatus(useSaveStatus);
setShowCompletedUploadFiles(true); //not sure we need this here if it does it on drop of file
//uploadAppealFiles(values);
uploadAppealFiles(values)
.then((data) => {
// console.log( // console.log(
// "\n////////////////////////\n appeal pdf payload", // "\n////////////////////////\n appeal pdf payload",
// values, // values,
@@ -202,12 +201,7 @@ let BuildSection = (props) => {
// ), // ),
props.setNewAppealProgress( props.setNewAppealProgress(
getProgressObj( getProgressObj(formXML, titleList, mandatoryFieldsData, props)
formXML,
titleList,
mandatoryFieldsData,
props
)
); );
let appTypeCollection = getFormCollectionByID( let appTypeCollection = getFormCollectionByID(
@@ -219,9 +213,7 @@ let BuildSection = (props) => {
Object.assign(updateBody, { Object.assign(updateBody, {
"pinswg_appealcasetype": props.appealType.appealTypeID, "pinswg_appealcasetype": props.appealType.appealTypeID,
"pinswg_Appellant@odata.bind": "pinswg_Appellant@odata.bind":
"/contacts(" + "/contacts(" + props.props.accountDetails.loggedinUserId + ")",
props.props.accountDetails.loggedinUserId +
")",
"pinswg_name": props.appealType.caseReference.ticketnumber, "pinswg_name": props.appealType.caseReference.ticketnumber,
[updateBindAppealTypeToIncident + "@odata.bind"]: [updateBindAppealTypeToIncident + "@odata.bind"]:
"/incidents(" + incidentId + ")", "/incidents(" + incidentId + ")",
@@ -243,25 +235,19 @@ let BuildSection = (props) => {
//console.log(updateBody); //console.log(updateBody);
let updateFormCollection = let updateFormCollection = appTypeCollection.LogicalCollectionName;
appTypeCollection.LogicalCollectionName;
let primaryAttribute = appTypeCollection.PrimaryIdAttribute; let primaryAttribute = appTypeCollection.PrimaryIdAttribute;
const reference = "PEDW-PARTIAL"; const reference = "PEDW-PARTIAL";
const templateId = "021b0a7b-df00-41f1-b94e-c269bee98c75"; const templateId = "021b0a7b-df00-41f1-b94e-c269bee98c75";
const templateIdCY = "f3c4a56b-bfb8-4d39-97dd-888df3062b0a"; const templateIdCY = "f3c4a56b-bfb8-4d39-97dd-888df3062b0a";
const emailAddress = const emailAddress = props.props.accountDetails.loggedinUserEmail;
props.props.accountDetails.loggedinUserEmail;
const personalisation = { const personalisation = {
"caseReference": "caseReference": props.appealType.caseReference.ticketnumber,
props.appealType.caseReference.ticketnumber, "emailAddress": props.props.accountDetails.loggedinUserEmail,
"emailAddress":
props.props.accountDetails.loggedinUserEmail,
"returnLink": "returnLink":
props.props.url + props.props.url +
(router.locale != "en" (router.locale != "en" ? "/cy/fymhorth/" : "/myportal/") +
? "/cy/fymhorth/"
: "/myportal/") +
appTypeCollection.UrlName + appTypeCollection.UrlName +
"?lpa=" + "?lpa=" +
props.appealType.appealLPA + props.appealType.appealLPA +
@@ -290,8 +276,7 @@ let BuildSection = (props) => {
// props.appealType.caseReference.incidentid, // props.appealType.caseReference.incidentid,
// "/////////////////////////////////" // "/////////////////////////////////"
// ); // );
})
.then(() => {
sendSavedEmail == true && sendSavedEmail == true &&
sendEmail( sendEmail(
router.locale != "en" ? templateIdCY : templateId, router.locale != "en" ? templateIdCY : templateId,
@@ -306,10 +291,6 @@ let BuildSection = (props) => {
? "/" + router.locale + "/myportal" ? "/" + router.locale + "/myportal"
: "/myportal" : "/myportal"
); );
})
.then(() => {
setCompletedUploadFiles(true);
});
}; };
const onHandleSubmit = (values) => { const onHandleSubmit = (values) => {
@@ -617,7 +598,7 @@ let BuildSection = (props) => {
"_pinswg_appellant_value" "_pinswg_appellant_value"
]; ];
console.log("on save:", valuesObj); //console.log("on save:", valuesObj);
updateCaseProgress( updateCaseProgress(
valuesObj, valuesObj,
true, true,
+1 -1
View File
@@ -111,5 +111,5 @@
"planning-obligation-(s106/unilateral)": "Rhwymedigaeth gynllunio (S106/Unochrog)", "planning-obligation-(s106/unilateral)": "Rhwymedigaeth gynllunio (S106/Unochrog)",
"site-location-plan": "Cynllun Lleoliad Safle", "site-location-plan": "Cynllun Lleoliad Safle",
"registration-of-application-letter": "Llythyr Cofrestru Cais", "registration-of-application-letter": "Llythyr Cofrestru Cais",
"previously-added-files": "Ffeiliau a ychwanegwyd yn flaenorol" "previously-added-files": "Ffeiliau wedi'u llwytho i fyny"
} }
+1 -1
View File
@@ -111,5 +111,5 @@
"planning-obligation-(s106/unilateral)": "Planning obligation (S106/Unilateral)", "planning-obligation-(s106/unilateral)": "Planning obligation (S106/Unilateral)",
"site-location-plan": "Site Location Plan", "site-location-plan": "Site Location Plan",
"registration-of-application-letter": "Registration of Application letter", "registration-of-application-letter": "Registration of Application letter",
"previously-added-files": "Previously added files" "previously-added-files": "Uploaded files"
} }
+49
View File
@@ -0,0 +1,49 @@
import {
downloadAllProgressFiles,
getAllProgressBlobs,
} from "../../../actions/azurestorage";
import _ from "lodash";
import nextConnect from "next-connect";
import middleware from "../middleware/middleware";
import {
getToken,
azureHeaders,
consoleLogger,
hashAPIPath,
} from "../../../actions";
import axios from "axios";
import CryptoJS from "crypto-js";
const WORDKEY = process.env.HASHKEY;
const WEBAPI_URL =
process.env.RELAY_ROOT ||
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
const BASE_URL = process.env.API_ROOT || `http://localhost:${port}`;
export default async function ApiProxy(req, res) {
var containerName = req.query.container;
var casefolderID = req.query.casefolderID;
var checkHash = req.query.hash;
var token = await getToken();
var queryUrl =
"/api/file/getbloblist?container=" +
containerName +
"&casefolderID=" +
casefolderID;
return axios
.get(
BASE_URL + queryUrl + hashAPIPath(queryUrl),
azureHeaders(token.access_token)
)
.then(({ data }) => {
res.status(200).json(data);
})
.catch((error) => {
consoleLogger(error);
res.status(400).json(error);
});
}
+11
View File
@@ -2483,6 +2483,7 @@ ul#sharePageLinks.active {
} }
} }
// modal timeout // modal timeout
.modal { .modal {
@@ -2655,6 +2656,10 @@ fade {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
.govuk-summary-list__actionLink.watched_link {
width: 10px;
}
} }
@@ -2904,4 +2909,10 @@ fade {
} }
} }
}
ul.subFieldList {
padding-left: 0;
} }