5454 </NcButton >
5555 </div >
5656 <div class =" image-page" >
57- <PdfEditor ref =" pdfEditor"
57+ <PdfEditor v-if =" !isEnvelope || envelopeFilesReady"
58+ ref =" pdfEditor"
5859 width =" 100%"
5960 height =" 100%"
60- :files =" [document.file] "
61- :file-names =" [documentNameWithExtension] "
61+ :files =" pdfFiles "
62+ :file-names =" pdfFileNames "
6263 @pdf-editor:end-init =" updateSigners"
6364 @pdf-editor:on-delete-signer =" onDeleteSigner" />
6465 </div >
@@ -108,6 +109,11 @@ export default {
108109 signerSelected: null ,
109110 width: getCapabilities ().libresign .config [' sign-elements' ][' full-signature-width' ],
110111 height: getCapabilities ().libresign .config [' sign-elements' ][' full-signature-height' ],
112+ envelopeFiles: [],
113+ filePagesMap: {},
114+ envelopeFilesReady: false ,
115+ elementsLoaded: false ,
116+ loadedPdfsCount: 0 ,
111117 }
112118 },
113119 computed: {
@@ -126,8 +132,31 @@ export default {
126132 document () {
127133 return this .filesStore .getFile ()
128134 },
135+ isEnvelope () {
136+ return this .document ? .nodeType === ' envelope'
137+ },
138+ pdfFiles () {
139+ if (this .isEnvelope ) {
140+ if (! this .envelopeFilesReady ) return []
141+ return this .envelopeFiles .map (f => f .file )
142+ }
143+ return [this .document .file ]
144+ },
145+ pdfFileNames () {
146+ if (this .isEnvelope ) {
147+ if (! this .envelopeFilesReady ) return []
148+ return this .envelopeFiles .map (f => {
149+ const metadata = typeof f .metadata === ' string' ? JSON .parse (f .metadata ) : f .metadata
150+ return ` ${ f .name } .${ metadata? .extension || ' pdf' }`
151+ })
152+ }
153+ return [this.documentNameWithExtension]
154+ },
129155 documentNameWithExtension() {
130156 const doc = this.document
157+ if (!doc.metadata?.extension) {
158+ return doc.name
159+ }
131160 return ` ${doc .name }.$ {doc .metadata .extension }`
132161 },
133162 canSign() {
@@ -168,7 +197,7 @@ export default {
168197 unsubscribe('libresign:visible-elements-select-signer')
169198 },
170199 methods: {
171- showModal () {
200+ async showModal() {
172201 if (!this.canRequestSign) {
173202 return
174203 }
@@ -177,17 +206,103 @@ export default {
177206 }
178207 this.modal = true
179208 this.filesStore.loading = true
209+
210+ if (this.isEnvelope) {
211+ await this.loadEnvelopeFiles()
212+ }
213+
214+ this.filesStore.loading = false
215+ },
216+ buildFilePagesMap() {
217+ if (!this.isEnvelope || this.envelopeFiles.length === 0) {
218+ return
219+ }
220+
221+ let currentPage = 1
222+ this.envelopeFiles.forEach((file, index) => {
223+ const metadata = typeof file.metadata === 'string' ? JSON.parse(file.metadata) : file.metadata
224+ const pageCount = metadata?.p || 0
225+
226+ for (let i = 0; i < pageCount; i++) {
227+ this.filePagesMap[currentPage + i] = {
228+ uuid: file.uuid,
229+ fileIndex: index,
230+ startPage: currentPage,
231+ fileName: file.name,
232+ }
233+ }
234+ currentPage += pageCount
235+ })
180236 },
181237 closeModal() {
182238 this.modal = false
183239 this.filesStore.loading = false
240+ this.envelopeFilesReady = false
241+ this.elementsLoaded = false
242+ this.loadedPdfsCount = 0
243+ },
244+ async loadEnvelopeFiles() {
245+ if (!this.document?.nodeId) {
246+ this.filesStore.loading = false
247+ return
248+ }
249+
250+ try {
251+ const url = generateOcsUrl('/apps/libresign/api/v1/file/list')
252+ const params = new URLSearchParams({
253+ page: '1',
254+ length: '100',
255+ parentNodeId: this.document.nodeId.toString(),
256+ })
257+
258+ const { data } = await axios.get(` ${url}? ${params .toString ()}` )
259+ if (data.ocs?.data?.data) {
260+ this.envelopeFiles = data.ocs.data.data
261+ this.envelopeFilesReady = true
262+
263+ this.buildFilePagesMap()
264+ }
265+ } catch (error) {
266+ showError(this.$t('libresign', 'Failed to load envelope files'))
267+ this.filesStore.loading = false
268+ }
184269 },
185270 updateSigners(data) {
271+ this.loadedPdfsCount++
272+
273+ if (this.isEnvelope) {
274+ const expectedPdfsCount = this.envelopeFiles.length
275+
276+ if (this.elementsLoaded || this.loadedPdfsCount < expectedPdfsCount) {
277+ return
278+ }
279+ }
280+
186281 this.document.signers.forEach(signer => {
187282 if (this.document.visibleElements) {
188283 Object.values(this.document.visibleElements).forEach(element => {
189284 if (element.signRequestId === signer.signRequestId) {
190285 const object = structuredClone(signer)
286+
287+ if (this.isEnvelope && element.uuid) {
288+ const fileInfo = this.envelopeFiles.find(f => f.uuid === element.uuid)
289+
290+ if (fileInfo) {
291+ for (const [page, info] of Object.entries(this.filePagesMap)) {
292+ if (info.uuid === element.uuid) {
293+ object.element = {
294+ ...element,
295+ documentIndex: info.fileIndex,
296+ }
297+ object.element.coordinates.ury = Math.round(data.measurement[element.coordinates.page].height)
298+ - element.coordinates.ury
299+ this.$refs.pdfEditor.addSigner(object)
300+ return
301+ }
302+ }
303+ }
304+ }
305+
191306 element.coordinates.ury = Math.round(data.measurement[element.coordinates.page].height)
192307 - element.coordinates.ury
193308 object.element = element
@@ -196,6 +311,11 @@ export default {
196311 })
197312 }
198313 })
314+
315+ if (this.isEnvelope) {
316+ this.elementsLoaded = true
317+ }
318+
199319 this.filesStore.loading = false
200320 },
201321 onSelectSigner(signer) {
@@ -210,11 +330,25 @@ export default {
210330 },
211331 doSelectSigner(event) {
212332 const canvasList = this.$refs.pdfEditor.$refs.vuePdfEditor.$refs.pdfBody.querySelectorAll('canvas')
213- const page = Array .from (canvasList).indexOf (event .target )
214- this .addSignerToPosition (event , page)
333+ const canvasIndex = Array.from(canvasList).indexOf(event.target)
334+ const globalPageNumber = canvasIndex + 1 // 1-based
335+
336+ let documentIndex = 0
337+ let pageInDocument = globalPageNumber
338+
339+ if (this.isEnvelope && this.filePagesMap[globalPageNumber]) {
340+ const pageInfo = this.filePagesMap[globalPageNumber]
341+ documentIndex = pageInfo.fileIndex
342+ pageInDocument = globalPageNumber - pageInfo.startPage + 1
343+ console.log(` Canvas ${canvasIndex} (global page ${globalPageNumber}) → documentIndex: ${documentIndex}, page: ${pageInDocument}` )
344+ } else {
345+ console.log(` Canvas ${canvasIndex} → page: ${pageInDocument}` )
346+ }
347+
348+ this.addSignerToPosition(event, pageInDocument, documentIndex)
215349 this.stopAddSigner()
216350 },
217- addSignerToPosition (event , page ) {
351+ addSignerToPosition(event, pageInDocument, documentIndex ) {
218352 const canvas = event.target
219353 const rect = canvas.getBoundingClientRect()
220354 const scale = this.$refs.pdfEditor.$refs.vuePdfEditor.scale || 1
@@ -232,13 +366,18 @@ export default {
232366
233367 this.signerSelected.element = {
234368 coordinates: {
235- page: page + 1 ,
369+ page: pageInDocument ,
236370 llx: normalizedX - this.width / 2,
237371 ury: normalizedY - this.height / 2,
238372 width: this.width,
239373 height: this.height,
240374 },
241375 }
376+
377+ if (this.isEnvelope && documentIndex > 0) {
378+ this.signerSelected.element.documentIndex = documentIndex
379+ }
380+
242381 this.$refs.pdfEditor.addSigner(this.signerSelected)
243382 },
244383 stopAddSigner() {
@@ -282,26 +421,49 @@ export default {
282421 },
283422 buildVisibleElements() {
284423 const visibleElements = []
285- const objects = this .$refs .pdfEditor .$refs .vuePdfEditor .getAllObjects ()
286-
287- objects .forEach (object => {
288- if (! object .signer ) return
289-
290- visibleElements .push ({
291- type: ' signature' ,
292- signRequestId: object .signer .signRequestId ,
293- elementId: object .signer .element .elementId ,
294- coordinates: {
295- page: object .pageNumber ,
296- width: object .normalizedCoordinates .width ,
297- height: object .normalizedCoordinates .height ,
298- llx: object .normalizedCoordinates .llx ,
299- lly: object .normalizedCoordinates .lly ,
300- ury: object .normalizedCoordinates .ury ,
301- urx: object .normalizedCoordinates .urx ,
302- },
424+
425+ const numDocuments = this.isEnvelope ? this.envelopeFiles.length : 1
426+
427+ for (let docIndex = 0; docIndex < numDocuments; docIndex++) {
428+ const objects = this.$refs.pdfEditor.$refs.vuePdfEditor.getAllObjects(docIndex)
429+
430+ objects.forEach(object => {
431+ if (!object.signer) return
432+
433+ let globalPageNumber = object.pageNumber
434+ if (this.isEnvelope && docIndex > 0) {
435+ for (const [page, info] of Object.entries(this.filePagesMap)) {
436+ if (info.fileIndex === docIndex) {
437+ globalPageNumber = info.startPage + object.pageNumber - 1
438+ break
439+ }
440+ }
441+ }
442+
443+ const element = {
444+ type: 'signature',
445+ signRequestId: object.signer.signRequestId,
446+ elementId: object.signer.element.elementId,
447+ coordinates: {
448+ page: globalPageNumber,
449+ width: object.normalizedCoordinates.width,
450+ height: object.normalizedCoordinates.height,
451+ llx: object.normalizedCoordinates.llx,
452+ lly: object.normalizedCoordinates.lly,
453+ ury: object.normalizedCoordinates.ury,
454+ urx: object.normalizedCoordinates.urx,
455+ },
456+ }
457+
458+ if (this.isEnvelope && this.filePagesMap[globalPageNumber]) {
459+ element.uuid = this.filePagesMap[globalPageNumber].uuid
460+ element.coordinates.page = globalPageNumber - this.filePagesMap[globalPageNumber].startPage + 1
461+ }
462+
463+ visibleElements.push(element)
303464 })
304- })
465+ }
466+
305467 return visibleElements
306468 },
307469 },
0 commit comments