Skip to content

Commit 2d53b0d

Browse files
committed
feat: add support to multiple documents when add visible elements
Signed-off-by: Vitor Mattos <[email protected]>
1 parent bd91f51 commit 2d53b0d

File tree

2 files changed

+195
-27
lines changed

2 files changed

+195
-27
lines changed

src/Components/PdfEditor/PdfEditor.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,15 @@ export default {
8383
x: signer.element.coordinates.llx,
8484
y: signer.element.coordinates.ury,
8585
}
86+
87+
const docIndex = signer.element.documentIndex !== undefined
88+
? signer.element.documentIndex
89+
: this.$refs.vuePdfEditor.selectedDocIndex
90+
8691
this.$refs.vuePdfEditor.addObjectToPage(
8792
object,
8893
signer.element.coordinates.page - 1,
94+
docIndex,
8995
)
9096
},
9197
},

src/Components/Request/VisibleElements.vue

Lines changed: 189 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,12 @@
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

Comments
 (0)