Skip to content

Commit 5ec6775

Browse files
authored
Merge pull request #8564 from ProcessMaker/defect/FOUR-25983
defect/FOUR-25983: [47027] Ellucian - Printed Form cuts fields after PDF Preview when it starts at top of a new page
2 parents 0834ec0 + 32da994 commit 5ec6775

File tree

1 file changed

+192
-49
lines changed

1 file changed

+192
-49
lines changed

resources/js/requests/components/screenDetail.vue

Lines changed: 192 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
<template>
2-
<div class="card h-100">
2+
<div class="card">
33
<b-overlay
4-
id="overlay-background"
5-
:show="disabled"
6-
:variant="variant"
7-
:opacity="opacity"
8-
:blur="blur"
9-
rounded="sm"
4+
id="overlay-background"
5+
:show="disabled"
6+
:variant="variant"
7+
:opacity="opacity"
8+
:blur="blur"
9+
rounded="sm"
10+
>
11+
<div class="w-100 d-print-none" align="right">
12+
<button
13+
type="button"
14+
@click="print"
15+
class="btn btn-secondary ml-2"
16+
:aria-label="$t('Print')"
17+
v-if="canPrint"
18+
:disabled="disabled"
1019
>
11-
<div class="w-100 d-print-none" align="right">
12-
<button
13-
type="button"
14-
@click="print"
15-
class="btn btn-secondary ml-2"
16-
:aria-label="$t('Print')"
17-
v-if="canPrint"
18-
:disabled="disabled"
19-
>
20-
<i class="fas fa-print"></i> {{ $t("Print") }}
21-
</button>
22-
</div>
23-
<div v-for="page in printablePages" :key="page" class="card">
24-
<div class="card-body h-100" :style="cardStyles">
20+
<i class="fas fa-print"></i> {{ $t("Print") }}
21+
</button>
22+
</div>
23+
<div class="card-body" :style="cardStyles">
2524
<component
2625
ref="print"
2726
:is="component"
@@ -34,20 +33,19 @@
3433
token-id=""
3534
/>
3635
</div>
37-
</div>
38-
<div class="w-100 d-print-none" align="right">
39-
<button
40-
type="button"
41-
@click="print"
42-
v-if="canPrint"
43-
class="btn btn-secondary ml-2"
44-
:aria-label="$t('Print')"
45-
:disabled="disabled"
46-
>
47-
<i class="fas fa-print"></i> {{ $t("Print") }}
48-
</button>
49-
</div>
50-
</b-overlay>
36+
<div class="w-100 d-print-none" align="right">
37+
<button
38+
type="button"
39+
@click="print"
40+
v-if="canPrint"
41+
class="btn btn-secondary ml-2"
42+
:aria-label="$t('Print')"
43+
:disabled="disabled"
44+
>
45+
<i class="fas fa-print"></i> {{ $t("Print") }}
46+
</button>
47+
</div>
48+
</b-overlay>
5149
</div>
5250
</template>
5351

@@ -106,13 +104,9 @@
106104
}
107105
},
108106
printablePages() {
109-
const pages = [0];
110-
if (this.rowData.config instanceof Array) {
111-
this.rowData.config.forEach(page => {
112-
this.findPagesInNavButtons(page, pages);
113-
});
114-
}
115-
return pages;
107+
// New strategy: always return only page 0
108+
// This avoids any problem with the detection of pages
109+
return [0];
116110
},
117111
component() {
118112
if ('renderComponent' in this.rowData.config) {
@@ -157,11 +151,10 @@
157151
},
158152
loadPages() {
159153
this.$nextTick(() => {
160-
this.$refs.print.forEach((page, index) => {
161-
if (page.setCurrentPage) {
162-
page.setCurrentPage(this.printablePages[index]);
163-
}
164-
});
154+
if (this.$refs.print && this.$refs.print.setCurrentPage) {
155+
// Force page 0
156+
this.$refs.print.setCurrentPage(0);
157+
}
165158
});
166159
},
167160
findPagesInNavButtons(object, found = []) {
@@ -175,7 +168,72 @@
175168
});
176169
} else if (object.config && object.config.event === 'pageNavigate' && object.config.eventData) {
177170
const page = parseInt(object.config.eventData);
178-
found.indexOf(page) === -1 ? found.push(page) : null;
171+
if (found.indexOf(page) === -1) {
172+
found.push(page);
173+
}
174+
}
175+
// Also search in the structure of pages of the form
176+
if (object.component === 'FormMultiColumn' && object.config && object.config.pages) {
177+
object.config.pages.forEach((page, index) => {
178+
if (found.indexOf(index) === -1) {
179+
found.push(index);
180+
}
181+
});
182+
}
183+
// Search in components that can have pagination
184+
if (object.component === 'FormPage' && object.config && object.config.page) {
185+
const page = parseInt(object.config.page);
186+
if (found.indexOf(page) === -1) {
187+
found.push(page);
188+
}
189+
}
190+
},
191+
hasRealContent(item) {
192+
// Verify if the element has real content that should be shown
193+
if (!item) return false;
194+
195+
// If it is a component that should not be shown in print, it does not have content
196+
if (item.component === 'FormButton' || item.component === 'FileUpload' || item.component === 'PhotoVideo') {
197+
return false;
198+
}
199+
200+
// If it has items, verify if any of them has content
201+
if (item.items && item.items.length > 0) {
202+
return item.items.some(child => this.hasRealContent(child));
203+
}
204+
205+
// If it is an array, verify if any of them has content
206+
if (item instanceof Array) {
207+
return item.some(child => this.hasRealContent(child));
208+
}
209+
210+
// If it has a valid component, it has content
211+
if (item.component && item.component !== 'FormButton' && item.component !== 'FileUpload' && item.component !== 'PhotoVideo') {
212+
return true;
213+
}
214+
215+
return false;
216+
},
217+
findAllPagesWithContent(config, pages) {
218+
if (config instanceof Array) {
219+
config.forEach((item, index) => {
220+
if (this.hasRealContent(item)) {
221+
if (pages.indexOf(index) === -1) {
222+
pages.push(index);
223+
}
224+
}
225+
// Search recursively in the items
226+
if (item.items) {
227+
this.findAllPagesWithContent(item.items, pages);
228+
}
229+
});
230+
} else if (config.items) {
231+
this.findAllPagesWithContent(config.items, pages);
232+
} else if (config.component && config.component !== 'FormButton' && config.component !== 'FileUpload' && config.component !== 'PhotoVideo') {
233+
// If it is a valid component, include page 0
234+
if (pages.indexOf(0) === -1) {
235+
pages.push(0);
236+
}
179237
}
180238
},
181239
/**
@@ -212,7 +270,25 @@
212270
ProcessMaker.EventBus.$emit('form-data-updated', data);
213271
},
214272
print() {
215-
window.print();
273+
// Ensure that the content is rendered completely before printing
274+
this.$nextTick(() => {
275+
// Force the re-rendering of all components
276+
this.$forceUpdate();
277+
278+
// Small delay to ensure that the DOM is updated
279+
setTimeout(() => {
280+
// Apply specific styles for print
281+
document.body.classList.add('printing');
282+
283+
// Open the print dialog
284+
window.print();
285+
286+
// Clean the class after a time
287+
setTimeout(() => {
288+
document.body.classList.remove('printing');
289+
}, 1000);
290+
}, 100);
291+
});
216292
return true;
217293
}
218294
},
@@ -230,3 +306,70 @@
230306
}
231307
</script>
232308

309+
<style scoped>
310+
@media print {
311+
.card {
312+
overflow: visible !important;
313+
height: auto !important;
314+
max-height: none !important;
315+
page-break-inside: avoid;
316+
}
317+
318+
.card-body {
319+
overflow: visible !important;
320+
height: auto !important;
321+
max-height: none !important;
322+
}
323+
324+
.h-100 {
325+
height: auto !important;
326+
max-height: none !important;
327+
}
328+
329+
/* Ensure that all elements of the form are visible */
330+
.card-body * {
331+
overflow: visible !important;
332+
}
333+
334+
/* Avoid that the elements are cut */
335+
.form-group,
336+
.form-control,
337+
.input-group {
338+
overflow: visible !important;
339+
height: auto !important;
340+
}
341+
}
342+
343+
/* Additional styles when printing */
344+
body.printing .card {
345+
overflow: visible !important;
346+
height: auto !important;
347+
max-height: none !important;
348+
}
349+
350+
body.printing .card-body {
351+
overflow: visible !important;
352+
height: auto !important;
353+
max-height: none !important;
354+
}
355+
356+
body.printing .h-100 {
357+
height: auto !important;
358+
max-height: none !important;
359+
}
360+
361+
/* Avoid empty pages */
362+
@media print {
363+
.card:empty,
364+
.card-body:empty {
365+
display: none !important;
366+
}
367+
368+
/* Ensure that the content is shown correctly */
369+
.card {
370+
page-break-inside: avoid;
371+
break-inside: avoid;
372+
}
373+
}
374+
</style>
375+

0 commit comments

Comments
 (0)