diff --git a/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MCS.FOI.MSGToPDF.csproj b/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MCS.FOI.MSGToPDF.csproj index 7d8eb110a..c00789360 100644 --- a/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MCS.FOI.MSGToPDF.csproj +++ b/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MCS.FOI.MSGToPDF.csproj @@ -12,7 +12,7 @@ - + diff --git a/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MSGFileProcessor.cs b/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MSGFileProcessor.cs index c3998d3b9..e637a8b82 100644 --- a/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MSGFileProcessor.cs +++ b/MCS.FOI.S3FileConversion/MCS.FOI.MSGToPDF/MSGFileProcessor.cs @@ -12,6 +12,9 @@ using System.Collections.Generic; using Syncfusion.Pdf.HtmlToPdf; using System.ComponentModel.DataAnnotations; +using System; +using RtfPipe.Tokens; +using System.IO; namespace MCS.FOI.MSGToPDF { @@ -96,12 +99,10 @@ public MSGFileProcessor(Stream sourceStream) filename = Path.GetFileNameWithoutExtension(filename) + '1' + extension; } - Console.WriteLine("attachmentname: " + _attachment.FileName); - Console.WriteLine("attachmentpos: " + _attachment.RenderingPosition); - Console.WriteLine("attachmentmime: " + extension); fileNameHash.Add(filename, true); attachmentInfo.Add("filename", _attachment.FileName); attachmentInfo.Add("s3filename", filename); + attachmentInfo.Add("cid", _attachment.ContentId); attachmentInfo.Add("size", _attachment.Data.Length.ToString()); attachmentInfo.Add("lastmodified", _attachment.LastModificationTime.ToString()); attachmentInfo.Add("created", _attachment.CreationTime.ToString()); @@ -109,32 +110,12 @@ public MSGFileProcessor(Stream sourceStream) } } } - - //msg.CharsetDetectionEncodingConfidenceLevel = 0.7f; if (msg.BodyRtf != null) { - //using var fs0 = new FileStream("C:\\folder\\log.txt", FileMode.Create, FileAccess.Write); var msgReader = new Reader(); var inputStream = new MemoryStream(); - //SourceStream.CopyTo(inputStream); - //List result = msgReader.ExtractToStream(inputStream, true); - - - //using var htmlfs = new FileStream("C:\\folder\\test.txt", FileMode.Create, FileAccess.Write); - //result[0].WriteTo(htmlfs); - //string bin = BitConverter.ToString(((Storage.Attachment)msg.Attachments[0]).Data).Replace("-", string.Empty); - //Console.WriteLine(bin); string body = msgReader.ExtractMsgEmailBody(SourceStream, ReaderHyperLinks.Both, "text/html; charset=utf-8", false); - //var ms = new MemoryStream(); - //var success = false; - //(ms, success) = ConvertHTMLtoPDF(body, ms); - - //using var fs1 = new FileStream("C:\\folder\\blinkconverted.pdf", FileMode.Create, FileAccess.Write); - using var fs2 = new FileStream("C:\\folder\\syncfusionconverted.pdf", FileMode.Create, FileAccess.Write); - //using var fs3 = new FileStream("C:\\folder\\syncfusionconverted.docx", FileMode.Create, FileAccess.Write); - //using var fs4 = new FileStream("C:\\folder\\test.txt", FileMode.Create, FileAccess.Write); - //ms.WriteTo(fs1); var bodyreplaced = Regex.Replace(Regex.Replace(body.Replace("
", "
").Replace("", "").Replace("", ""), "=(?(?!utf-8)[\\w|-]+)", "=\"${tagname}\""), "", ""); const string rtfInlineObject = "[*[RTFINLINEOBJECT]*]"; const string imgString = ""); - var width = float.Parse(Regex.Match(match.Value, "(?<=width=\")\\d+").Value); - var height = float.Parse(Regex.Match(match.Value, "(?<=height=\")\\d+").Value); - const float maxSize = 750; - if (width > maxSize) - { - float scale = maxSize / width; - width = maxSize; - height = scale * height; - } - else if (height > maxSize) + bodyreplaced = Regex.Replace(bodyreplaced, "", ""); + foreach (KeyValuePair> attachment in attachmentsObj) { - float scale = maxSize / height; - height = maxSize; - width = scale * width; + if (attachment.Value["cid"] == inlineAttachment.ContentId) + { + attachmentsObj.Remove(attachment.Key); + } } - bodyreplaced = Regex.Replace(bodyreplaced, "", ""); } else if (rtfInline) { - //using var fs5 = new FileStream("C:\\folder\\image.png", FileMode.Create, FileAccess.Write); - //fs5.Write(inlineAttachment.Data, 0, inlineAttachment.Data.Length); - bodyreplaced = ReplaceFirstOccurrence(bodyreplaced, rtfInlineObject, ""); - //var string1 = Convert.ToBase64String(inlineAttachment.Data); - //var string2 = BitConverter.ToString(inlineAttachment.Data).Replace("-", string.Empty); + if (inlineAttachment.OleAttachment) + { + bodyreplaced = ReplaceFirstOccurrence(bodyreplaced, rtfInlineObject, ""); + foreach (KeyValuePair> attachment in attachmentsObj) + { + if (attachment.Value["filename"] == inlineAttachment.FileName) + { + attachmentsObj.Remove(attachment.Key); + } + } + } + else + { + bodyreplaced = ReplaceFirstOccurrence(bodyreplaced, rtfInlineObject, " [**Inline Attachment - " + inlineAttachment.FileName + "**]"); + } } } } - byte[] byteArray = Encoding.ASCII.GetBytes(bodyreplaced); using (MemoryStream messageStream = new MemoryStream(byteArray)) - { - //messageStream.WriteTo(fs4); + { using (WordDocument rtfDoc = new WordDocument(messageStream, Syncfusion.DocIO.FormatType.Html)) { - //rtfDoc.Save(fs3, FormatType.Docx); // Replace leading tabs, issue with syncfusion rtfDoc.ReplaceFirst = true; var regex = new Regex(@"(\r)*(\n)*(\t)+", RegexOptions.Multiline); var occurences = rtfDoc.Replace(regex, "\r\n"); + List pictures = rtfDoc.FindAllItemsByProperty(EntityType.Picture, "", ""); + + if (pictures != null) + { + foreach (WPicture picture in pictures) + { + picture.LockAspectRatio = true; + const float maxSize = 500; + if (picture.Height > maxSize && picture.Height >= picture.Width) + { + var scale = (maxSize / picture.Height) * 100; + picture.HeightScale = scale; + picture.WidthScale = scale; + } + if (picture.Width > maxSize) + { + var scale = (maxSize / picture.Width) * 100; + picture.HeightScale = scale; + picture.WidthScale = scale; + } + } + } + //Gets all the hyperlink fields in the document List fields = rtfDoc.FindAllItemsByProperty(EntityType.Field, "FieldType", FieldType.FieldHyperlink.ToString()); @@ -311,6 +310,8 @@ public MSGFileProcessor(Stream sourceStream) //bool isConverted; //(output, isConverted) = ConvertHTMLtoPDF(htmlString, output); + + break; } diff --git a/api/dockerfile b/api/dockerfile index a94c918a0..b419472d2 100644 --- a/api/dockerfile +++ b/api/dockerfile @@ -2,7 +2,7 @@ # FROM python:3.8 # Necessary to pull images from bcgov and not hit Dockerhub quotas. -FROM artifacts.developer.gov.bc.ca/docker-remote/python:3.8.5-buster +FROM artifacts.developer.gov.bc.ca/docker-remote/python:3.10.8-buster EXPOSE 6402 # Keeps Python from generating .pyc files in the container diff --git a/api/dockerfile.local b/api/dockerfile.local index da79e4624..a3f3052a8 100644 --- a/api/dockerfile.local +++ b/api/dockerfile.local @@ -1,5 +1,5 @@ # For more information, please refer to https://aka.ms/vscode-docker-python -FROM python:3.8 +FROM python:3.10.8 EXPOSE 6402 # Keeps Python from generating .pyc files in the container diff --git a/api/migrations/versions/13766f2831b6_.py b/api/migrations/versions/13766f2831b6_.py new file mode 100644 index 000000000..74197ce86 --- /dev/null +++ b/api/migrations/versions/13766f2831b6_.py @@ -0,0 +1,31 @@ +"""empty message + +Revision ID: 13766f2831b6 +Revises: 36e7b771fbb5 +Create Date: 2023-10-03 13:53:19.344756 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "13766f2831b6" +down_revision = "36e7b771fbb5" +branch_labels = None +depends_on = None + + +def upgrade(): + op.execute( + 'ALTER TABLE public."Annotations" DROP CONSTRAINT "annotation_version_key";' + ) + op.execute( + 'ALTER TABLE public."Annotations" ADD CONSTRAINT annotation_version_redactionlayerid_key UNIQUE (annotationname, version, redactionlayerid);' + ) + + +def downgrade(): + op.execute( + 'ALTER TABLE public."Annotations" DROP CONSTRAINT "annotation_version_redactionlayerid_key";' + ) diff --git a/api/requirements.txt b/api/requirements.txt index e52bf3fd1..0f38dfc6a 100644 Binary files a/api/requirements.txt and b/api/requirements.txt differ diff --git a/api/reviewer_api/models/Annotations.py b/api/reviewer_api/models/Annotations.py index eb3511a6d..d68ee2db3 100644 --- a/api/reviewer_api/models/Annotations.py +++ b/api/reviewer_api/models/Annotations.py @@ -322,7 +322,11 @@ def __newannotation(cls, annot, redactionlayerid, userinfo) -> DefaultMethodResu ] insertstmt = insert(Annotation).values(values) upsertstmt = insertstmt.on_conflict_do_update( - index_elements=[Annotation.annotationname, Annotation.version], + index_elements=[ + Annotation.annotationname, + Annotation.version, + Annotation.redactionlayerid, + ], set_={ "isactive": False, "updatedby": userinfo, diff --git a/api/reviewer_api/resources/document.py b/api/reviewer_api/resources/document.py index 19f41deb0..b30e88bd7 100644 --- a/api/reviewer_api/resources/document.py +++ b/api/reviewer_api/resources/document.py @@ -99,7 +99,7 @@ def get(requestid): jsonObj = response.json() result = documentservice().getdocuments(requestid) - return json.dumps({"requeststatusid": jsonObj["requeststatusid"], "documents": result}), 200 + return json.dumps({"requeststatusid": jsonObj["requeststatusid"], "documents": result,"requestnumber":jsonObj["axisRequestId"]}), 200 except KeyError as err: return {'status': False, 'message':err.messages}, 400 except BusinessException as exception: diff --git a/api/reviewer_api/services/radactionservice.py b/api/reviewer_api/services/radactionservice.py index 283ade224..7145fa69b 100644 --- a/api/reviewer_api/services/radactionservice.py +++ b/api/reviewer_api/services/radactionservice.py @@ -48,15 +48,22 @@ def saveannotation(self, annotationschema, userinfo): result = annotationservice().saveannotation(annotationschema, userinfo) if ( result.success == True - and "foiministryrequestid" in annotationschema and "pageflags" in annotationschema and annotationschema["pageflags"] is not None ): - documentpageflagservice().bulksavepageflag( - annotationschema["foiministryrequestid"], - annotationschema["pageflags"], - userinfo, - ) + foiministryrequestid = None + if "foiministryrequestid" in annotationschema: + foiministryrequestid = annotationschema["foiministryrequestid"] + elif "sections" in annotationschema: + foiministryrequestid = annotationschema["sections"][ + "foiministryrequestid" + ] + if foiministryrequestid: + documentpageflagservice().bulksavepageflag( + foiministryrequestid, + annotationschema["pageflags"], + userinfo, + ) return result def deactivateannotation( diff --git a/computingservices/DedupeServices/DockerFile.bcgov b/computingservices/DedupeServices/DockerFile.bcgov index 2dbac7b5c..427e6e598 100644 --- a/computingservices/DedupeServices/DockerFile.bcgov +++ b/computingservices/DedupeServices/DockerFile.bcgov @@ -1,4 +1,4 @@ -FROM artifacts.developer.gov.bc.ca/docker-remote/python:3.10-slim +FROM artifacts.developer.gov.bc.ca/docker-remote/python:3.10.8-buster # Keeps Python from generating .pyc files in the container ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/computingservices/DedupeServices/Dockerfile.local b/computingservices/DedupeServices/Dockerfile.local index b74049eff..179ae3680 100644 --- a/computingservices/DedupeServices/Dockerfile.local +++ b/computingservices/DedupeServices/Dockerfile.local @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.10.8 # Keeps Python from generating .pyc files in the container ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/computingservices/PDFStitchServices/Dockerfile.local b/computingservices/PDFStitchServices/Dockerfile.local index b74049eff..179ae3680 100644 --- a/computingservices/PDFStitchServices/Dockerfile.local +++ b/computingservices/PDFStitchServices/Dockerfile.local @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.10.8 # Keeps Python from generating .pyc files in the container ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/computingservices/ZippingServices/Dockerfile.local b/computingservices/ZippingServices/Dockerfile.local index b74049eff..179ae3680 100644 --- a/computingservices/ZippingServices/Dockerfile.local +++ b/computingservices/ZippingServices/Dockerfile.local @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.10.8 # Keeps Python from generating .pyc files in the container ENV PYTHONDONTWRITEBYTECODE=1 diff --git a/web/src/actions/actionConstants.ts b/web/src/actions/actionConstants.ts index 3f56dcca3..b5734e11c 100644 --- a/web/src/actions/actionConstants.ts +++ b/web/src/actions/actionConstants.ts @@ -16,7 +16,8 @@ const ACTION_CONSTANTS = { SET_REQUEST_STATUS: "SET_REQUEST_STATUS", SET_REDACTION_LAYERS: "SET_REDACTION_LAYERS", SET_CURRENT_LAYER: "SET_CURRENT_LAYER", - INC_REDACTION_LAYER: "INC_REDACTION_LAYER" + INC_REDACTION_LAYER: "INC_REDACTION_LAYER", + SET_REQUEST_NUMBER:"SET_REQUEST_NUMBER" }; export default ACTION_CONSTANTS; diff --git a/web/src/actions/documentActions.ts b/web/src/actions/documentActions.ts index 70453bdd6..3916cef01 100644 --- a/web/src/actions/documentActions.ts +++ b/web/src/actions/documentActions.ts @@ -51,6 +51,13 @@ export const setRequestStatus = (data: any) => (dispatch:any) =>{ }) } +export const setRequestNumber = (data: any) => (dispatch:any) =>{ + dispatch({ + type:ACTION_CONSTANTS.SET_REQUEST_NUMBER, + payload:data + }) +} + export const setRedactionLayers = (data: any) => (dispatch:any) =>{ dispatch({ type:ACTION_CONSTANTS.SET_REDACTION_LAYERS, diff --git a/web/src/apiManager/services/docReviewerService.tsx b/web/src/apiManager/services/docReviewerService.tsx index 94679d246..ea0e68b9f 100644 --- a/web/src/apiManager/services/docReviewerService.tsx +++ b/web/src/apiManager/services/docReviewerService.tsx @@ -3,7 +3,7 @@ import { httpGETRequest, httpPOSTRequest, httpDELETERequest } from "../httpReque import API from "../endpoints"; import UserService from "../../services/UserService"; import { setRedactionInfo, setIsPageLeftOff, setSections, setPageFlags, - setDocumentList, setRequestStatus, setRedactionLayers, incrementLayerCount + setDocumentList, setRequestStatus, setRedactionLayers, incrementLayerCount, setRequestNumber } from "../../actions/documentActions"; import { store } from "../../services/StoreService"; import { useSelector } from "react-redux"; @@ -22,7 +22,7 @@ export const fetchDocuments = ( // res.data.documents has all documents including the incompatible ones, below code is to filter out the incompatible ones const __files = res.data.documents.filter((d: any) => !d.attributes.incompatible); store.dispatch(setDocumentList(__files) as any); - + store.dispatch(setRequestNumber(res.data.requestnumber) as any); store.dispatch(setRequestStatus(res.data.requeststatusid) as any); callback(res.data.documents); } else { @@ -86,17 +86,28 @@ export const saveAnnotation = ( sections?: object, ) => { let apiUrlPost: string = `${API.DOCREVIEWER_ANNOTATION}`; - let requestJSON = sections ?{ - "xml": annotation, - "sections": sections, - "redactionlayerid": redactionLayer - } : - { + let requestJSON = {}; + if (sections && pageFlags) { + requestJSON = { + "xml": annotation, + "sections": sections, + "pageflags":pageFlags, + "redactionlayerid": redactionLayer + } + } else if (sections) { + requestJSON = { + "xml": annotation, + "sections": sections, + "redactionlayerid": redactionLayer + } + } else { + requestJSON = { "xml": annotation, "pageflags":pageFlags, "foiministryrequestid":requestid, "redactionlayerid": redactionLayer } + } let useAppSelector = useSelector; httpPOSTRequest({url: apiUrlPost, data: requestJSON, token: UserService.getToken() || '', isBearer: true}) .then((res:any) => { diff --git a/web/src/components/FOI/Home/Redlining.js b/web/src/components/FOI/Home/Redlining.js index 5899d2265..bb523da48 100644 --- a/web/src/components/FOI/Home/Redlining.js +++ b/web/src/components/FOI/Home/Redlining.js @@ -55,9 +55,10 @@ import { createRedactionSectionsString, getSections, getValidSections, + updatePageFlags, } from "./utils"; import { Edit, MultiSelectEdit } from "./Edit"; -import _ from "lodash"; +import _, { forEach } from "lodash"; const Redlining = React.forwardRef( ( @@ -82,6 +83,11 @@ const Redlining = React.forwardRef( const requestStatus = useAppSelector( (state) => state.documents?.requeststatus ); + + const requestnumber = useAppSelector( + (state) => state.documents?.requestnumber + ); + const pageFlags = useAppSelector((state) => state.documents?.pageFlags); const redactionInfo = useSelector( (state) => state.documents?.redactionInfo @@ -790,7 +796,6 @@ const Redlining = React.forwardRef( ); } } else if (action === "modify") { - console.log(info); if ( info.source === "group" && newRedaction.astr.includes(annotations[0].Id) // if we are grouping the newly created annotations do not save @@ -1136,6 +1141,7 @@ const Redlining = React.forwardRef( let childAnnotations = []; let redactionSectionsIds = selectedSections; let redactionIds = []; + let pageSelectionList = []; for (const node of astr.getElementsByTagName("annots")[0].children) { let _redact = annotManager .getAnnotationsList() @@ -1151,14 +1157,28 @@ const Redlining = React.forwardRef( childAnnotation.X = _redact.X; childAnnotation.Y = _redact.Y; childAnnotation.FontSize = _redact.FontSize; + const fullpageredaction = _redact.getCustomData("trn-redaction-type"); + const displayedDoc = + pageMappedDocs.stitchedPageLookup[Number(node.attributes.page) + 1]; + + //page flag updates + + updatePageFlags( + defaultSections, + selectedSections, + fullpageredaction, + pageFlagTypes, + displayedDoc, + pageSelectionList + ); + if (redactionSectionsIds.length > 0) { let redactionSections = createRedactionSectionsString( sections, redactionSectionsIds ); childAnnotation.setContents(redactionSections); - const displayedDoc = - pageMappedDocs.stitchedPageLookup[Number(node.attributes.page) + 1]; + childAnnotation.setCustomData( "sections", JSON.stringify(getSections(sections, redactionSectionsIds)) @@ -1193,12 +1213,20 @@ const Redlining = React.forwardRef( saveAnnotation( requestid, astr, - (data) => {}, + (data) => { + setPageSelections([]); + fetchPageFlag(requestid, currentLayer.redactionlayerid, (error) => + console.log(error) + ); + }, (error) => { console.log(error); }, currentLayer.redactionlayerid, - null, + createPageFlagPayload( + pageSelectionList, + currentLayer.redactionlayerid + ), sectn ); @@ -1239,12 +1267,18 @@ const Redlining = React.forwardRef( childSection = redactionInfo[i]?.sections.annotationname; childAnnotation = annotManager.getAnnotationById(childSection); } + const displayedDoc = + pageMappedDocs.stitchedPageLookup[Number(redactionObj["pages"]) + 1]; + let pageSelectionList = [...pageSelections]; for (const node of astr.getElementsByTagName("annots")[0].children) { let redaction = annotManager.getAnnotationById(node.attributes.name); redaction.NoMove = true; + const fullpageredaction = + redaction.getCustomData("trn-redaction-type"); let coords = node.attributes.coords; let X = coords?.substring(0, coords.indexOf(",")); childAnnotation = getCoordinates(childAnnotation, redaction, X); + let redactionSectionsIds = selectedSections; if (redactionSectionsIds.length > 0) { let redactionSections = createRedactionSectionsString( @@ -1252,10 +1286,7 @@ const Redlining = React.forwardRef( redactionSectionsIds ); childAnnotation.setContents(redactionSections); - const displayedDoc = - pageMappedDocs.stitchedPageLookup[ - Number(redactionObj["pages"]) + 1 - ]; + childAnnotation.setCustomData( "sections", JSON.stringify(getSections(sections, redactionSectionsIds)) @@ -1294,17 +1325,50 @@ const Redlining = React.forwardRef( let jObj = parser.parseFromString(astr); // Assume xmlText contains the example XML let annots = jObj.getElementsByTagName("annots"); let annot = annots[0].children[0]; - saveAnnotation( - requestid, - astr, - (data) => {}, - (error) => { - console.log(error); - }, - currentLayer.redactionlayerid, - null, - sectn - ); + if (_resizeAnnot?.type === "redact") { + saveAnnotation( + requestid, + astr, + (data) => {}, + (error) => { + console.log(error); + }, + currentLayer.redactionlayerid, + null, + sectn + ); + } else { + //page flag updates + updatePageFlags( + defaultSections, + selectedSections, + fullpageredaction, + pageFlagTypes, + displayedDoc, + pageSelectionList + ); + saveAnnotation( + requestid, + astr, + (data) => { + setPageSelections([]); + fetchPageFlag( + requestid, + currentLayer.redactionlayerid, + (error) => console.log(error) + ); + }, + (error) => { + console.log(error); + }, + currentLayer.redactionlayerid, + createPageFlagPayload( + pageSelectionList, + currentLayer.redactionlayerid + ), + sectn + ); + } setSelectedSections([]); if (redactionSectionsIds.length > 0) { redactionObj.names?.forEach((name) => { @@ -1328,7 +1392,10 @@ const Redlining = React.forwardRef( (defaultSections.length > 0 && defaultSections[0] === 25) || selectedSections[0] === 25 ) { - pageFlagSelections[0].flagid = pageFlagTypes["In Progress"]; + pageFlagSelections = pageFlagSelections.map((flag) => { + flag.flagid = pageFlagTypes["In Progress"]; + return flag; + }); } // add section annotation var sectionAnnotations = []; @@ -1726,6 +1793,93 @@ const Redlining = React.forwardRef( return zipServiceMessage; }; + const stampPageNumberRedline = async (_docViwer, PDFNet, divisionsdocpages) => { + for ( + let pagecount = 1; + pagecount <= divisionsdocpages.length; + pagecount++ + ) { + const doc = await _docViwer.getPDFDoc(); + + // Run PDFNet methods with memory management + await PDFNet.runWithCleanup(async () => { + // lock the document before a write operation + // runWithCleanup will auto unlock when complete + doc.lock(); + const s = await PDFNet.Stamper.create( + PDFNet.Stamper.SizeType.e_relative_scale, + 0.3, + 0.3 + ); + + await s.setAlignment( + PDFNet.Stamper.HorizontalAlignment.e_horizontal_center, + PDFNet.Stamper.VerticalAlignment.e_vertical_bottom + ); + const font = await PDFNet.Font.create( + doc, + PDFNet.Font.StandardType1Font.e_courier + ); + await s.setFont(font); + const redColorPt = await PDFNet.ColorPt.init(0, 0, 128, 0.5); + await s.setFontColor(redColorPt); + await s.setTextAlignment(PDFNet.Stamper.TextAlignment.e_align_right); + await s.setAsBackground(false); + const pgSet = await PDFNet.PageSet.createRange(pagecount, pagecount); + + await s.stampText( + doc, + `${requestnumber} , Page ${ + divisionsdocpages[pagecount - 1].stitchedPageNo + }`, + pgSet + ); + }); + } + }; + + const stampPageNumberResponse = async (_docViwer,PDFNet)=>{ + + + + for(let pagecount =1 ; pagecount <= _docViwer.getPageCount() ; pagecount++) + { + + try { + let doc = null; + + let _docmain = _docViwer.getDocument(); + doc = await _docmain.getPDFDoc() + + + // Run PDFNet methods with memory management + await PDFNet.runWithCleanup(async () => { + + // lock the document before a write operation + // runWithCleanup will auto unlock when complete + doc.lock(); + const s = await PDFNet.Stamper.create(PDFNet.Stamper.SizeType.e_relative_scale, 0.3, 0.3); + + await s.setAlignment(PDFNet.Stamper.HorizontalAlignment.e_horizontal_center, PDFNet.Stamper.VerticalAlignment.e_vertical_bottom); + const font = await PDFNet.Font.create(doc, PDFNet.Font.StandardType1Font.e_courier); + await s.setFont(font); + const redColorPt = await PDFNet.ColorPt.init(0, 0, 128, 0.5); + await s.setFontColor(redColorPt); + await s.setTextAlignment(PDFNet.Stamper.TextAlignment.e_align_right); + await s.setAsBackground(false); + const pgSet = await PDFNet.PageSet.createRange(pagecount , pagecount); + + await s.stampText(doc, `${requestnumber} , Page ${pagecount}`, pgSet); + + }); + } + catch(err){ + console.log(err) + throw err; + } + } + } + const saveRedlineDocument = (_instance) => { let arr = []; const divisionFilesList = [...documentList, ...incompatibleFiles]; @@ -1886,7 +2040,8 @@ const Redlining = React.forwardRef( pageMappingsByDivisions[doc.documentid] ).length; totalPageCountIncludeRemoved += doc.pagecount; - + const { PDFNet } = _instance.Core; + PDFNet.initialize(); await _instance.Core.createDocument(doc.s3path_load, { loadAsPDF: true, }).then(async (docObj) => { @@ -1909,8 +2064,22 @@ const Redlining = React.forwardRef( // save to s3 once all doc stitched if (docCount == divObj.documentlist.length) { - // console.log("pagemapping: ", pageMappingsByDivisions); - // console.log("pagesToRemove: ", pagesToRemove); + + if(pageMappedDocs!=undefined) + { + let divisionstichpages = [] + let divisionsdocpages = Object.values(pageMappedDocs.docIdLookup).filter((obj) => { return obj.division === divObj.divisionid}).map((obj)=>{return obj.pageMappings}) + divisionsdocpages.forEach(function(_arr){ + _arr.forEach(function(value){ + divisionstichpages.push(value) + }) + + }) + + divisionstichpages.sort((a,b) => (a.stitchedPageNo > b.stitchedPageNo) ? 1 : ((b.stitchedPageNo > a.stitchedPageNo) ? -1 : 0)) + await stampPageNumberRedline(stitchedDocObj,PDFNet, divisionstichpages) + + } // remove duplicate and not responsive pages await stitchedDocObj.removePages(pagesToRemove); @@ -1999,7 +2168,7 @@ const Redlining = React.forwardRef( saveRedlineDocument(docInstance); break; case "responsepackage": - saveResponsePackage(docViewer, annotManager); + saveResponsePackage(docViewer, annotManager,docInstance); break; default: } @@ -2034,7 +2203,7 @@ const Redlining = React.forwardRef( }); }; - const saveResponsePackage = async (documentViewer, annotationManager) => { + const saveResponsePackage = async (documentViewer, annotationManager,_instance) => { const downloadType = "pdf"; let zipServiceMessage = { @@ -2119,12 +2288,19 @@ const Redlining = React.forwardRef( } } } + + + + let doc = documentViewer.getDocument(); let results = await annotationManager.applyRedactions(); // must apply redactions before removing pages await doc.removePages(pagesToRemove); - //apply redaction and save to s3 + const { PDFNet } = _instance.Core; + PDFNet.initialize() + await stampPageNumberResponse(documentViewer,PDFNet) + //apply redaction and save to s3 doc .getFileData({ // saves the document with annotations in it @@ -2142,7 +2318,6 @@ const Redlining = React.forwardRef( { filepath: res.s3path_save }, _blob, (_res) => { - console.log(_res); toast.update(toastID, { render: "Final package is saved to Object Storage", type: "success", @@ -2358,4 +2533,4 @@ const Redlining = React.forwardRef( } ); -export default Redlining; +export default Redlining; \ No newline at end of file diff --git a/web/src/components/FOI/Home/utils.js b/web/src/components/FOI/Home/utils.js index 7aedd0a3a..1ca14cd6e 100644 --- a/web/src/components/FOI/Home/utils.js +++ b/web/src/components/FOI/Home/utils.js @@ -95,3 +95,36 @@ export const createRedactionSectionsString = ( } return redactionSections; }; + +export const updatePageFlags = ( + defaultSections, + selectedSections, + fullpageredaction, + pageFlagTypes, + displayedDoc, + pageSelectionList +) => { + //page flag updates + if ( + (defaultSections.length > 0 && defaultSections[0] === 25) || + (selectedSections && selectedSections[0] === 25) + ) { + pageSelectionList.push({ + page: Number(displayedDoc?.page), + flagid: pageFlagTypes["In Progress"], + docid: displayedDoc?.docid, + }); + } else if (fullpageredaction === "fullPage") { + pageSelectionList.push({ + page: Number(displayedDoc?.page), + flagid: pageFlagTypes["Withheld in Full"], + docid: displayedDoc?.docid, + }); + } else if (selectedSections && selectedSections[0] !== 25) { + pageSelectionList.push({ + page: Number(displayedDoc?.page), + flagid: pageFlagTypes["Partial Disclosure"], + docid: displayedDoc?.docid, + }); + } +}; diff --git a/web/src/modules/documentReducer.ts b/web/src/modules/documentReducer.ts index b4d7a9c33..823c98ddc 100644 --- a/web/src/modules/documentReducer.ts +++ b/web/src/modules/documentReducer.ts @@ -12,6 +12,8 @@ const documents = (state = initialState, action:any)=> { return {...state, isPageLeftOff: action.payload}; case ACTION_CONSTANTS.SET_SECTIONS: return {...state, sections: action.payload}; + case ACTION_CONSTANTS.SET_REQUEST_NUMBER: + return {...state, requestnumber: action.payload}; case ACTION_CONSTANTS.SET_PAGE_FLAGS: return {...state, pageFlags: action.payload}; case ACTION_CONSTANTS.SET_DOCUMENT_LIST: