|
1 | 1 | <template> |
2 | | - <div class="card h-100"> |
| 2 | + <div class="card"> |
3 | 3 | <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" |
10 | 19 | > |
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"> |
25 | 24 | <component |
26 | 25 | ref="print" |
27 | 26 | :is="component" |
|
34 | 33 | token-id="" |
35 | 34 | /> |
36 | 35 | </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> |
51 | 49 | </div> |
52 | 50 | </template> |
53 | 51 |
|
|
106 | 104 | } |
107 | 105 | }, |
108 | 106 | 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]; |
116 | 110 | }, |
117 | 111 | component() { |
118 | 112 | if ('renderComponent' in this.rowData.config) { |
|
157 | 151 | }, |
158 | 152 | loadPages() { |
159 | 153 | 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 | + } |
165 | 158 | }); |
166 | 159 | }, |
167 | 160 | findPagesInNavButtons(object, found = []) { |
|
175 | 168 | }); |
176 | 169 | } else if (object.config && object.config.event === 'pageNavigate' && object.config.eventData) { |
177 | 170 | 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 | + } |
179 | 237 | } |
180 | 238 | }, |
181 | 239 | /** |
|
212 | 270 | ProcessMaker.EventBus.$emit('form-data-updated', data); |
213 | 271 | }, |
214 | 272 | 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 | + }); |
216 | 292 | return true; |
217 | 293 | } |
218 | 294 | }, |
|
230 | 306 | } |
231 | 307 | </script> |
232 | 308 |
|
| 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