@nixweb/nixloc-ui 0.0.307 → 0.0.309

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nixweb/nixloc-ui",
3
- "version": "0.0.307",
3
+ "version": "0.0.309",
4
4
  "description": "Componentes UI",
5
5
  "author": "Fábio Ávila <fabio@nixweb.com.br>",
6
6
  "private": false,
@@ -0,0 +1,111 @@
1
+ <template>
2
+ <div>
3
+ <div class="zoom-controls">
4
+ <transition name="fade">
5
+ <span v-if="showZoomLabel">{{ (zoom * 100).toFixed(0) }}%</span>
6
+ </transition>
7
+ </div>
8
+
9
+ <div class="zoom-container">
10
+ <div class="zoom-area" :style="zoomStyle">
11
+ <slot></slot>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+
19
+ import { mapGetters } from "vuex";
20
+
21
+ export default {
22
+ name: 'Zoom',
23
+ data() {
24
+ return {
25
+ zoom: 1,
26
+ zoomStep: 0.1,
27
+ zoomMin: 0.5,
28
+ zoomMax: 2.0,
29
+ showZoomLabel: false,
30
+ zoomTimeout: null
31
+ }
32
+ },
33
+ computed: {
34
+ ...mapGetters("generic", ["event"]),
35
+ zoomStyle() {
36
+ return {
37
+ transform: `scale(${this.zoom})`,
38
+ transformOrigin: 'top left',
39
+ width: `${100 / this.zoom}%`
40
+ }
41
+ }
42
+ },
43
+ methods: {
44
+ zoomIn() {
45
+ if (this.zoom < this.zoomMax) {
46
+ this.zoom += this.zoomStep
47
+ this.showZoomTemporarily()
48
+ }
49
+ },
50
+ zoomOut() {
51
+ if (this.zoom > this.zoomMin) {
52
+ this.zoom -= this.zoomStep
53
+ this.showZoomTemporarily()
54
+ }
55
+ },
56
+ showZoomTemporarily() {
57
+ this.showZoomLabel = true
58
+ clearTimeout(this.zoomTimeout)
59
+ this.zoomTimeout = setTimeout(() => {
60
+ this.showZoomLabel = false
61
+ }, 1000)
62
+ }
63
+ },
64
+ beforeDestroy() {
65
+ clearTimeout(this.zoomTimeout)
66
+ },
67
+ watch: {
68
+ event: {
69
+ handler(event) {
70
+ if (event.name == "zoomIn") this.zoomIn();
71
+ if (event.name == "zoomOut") this.zoomOut();
72
+ },
73
+ deep: true,
74
+ },
75
+
76
+ },
77
+ }
78
+ </script>
79
+
80
+ <style scoped>
81
+ .zoom-controls {
82
+ margin-bottom: 10px;
83
+ display: flex;
84
+ align-items: center;
85
+ gap: 8px;
86
+ }
87
+
88
+ .zoom-container {
89
+ overflow: auto;
90
+ width: 100%;
91
+ height: 100%;
92
+ }
93
+
94
+ .zoom-area {
95
+ background: #fff;
96
+ }
97
+
98
+ .fade-enter-active,
99
+ .fade-leave-active {
100
+ transition: opacity 0.5s ease;
101
+ }
102
+
103
+ .fade-enter,
104
+ .fade-leave-to {
105
+ opacity: 0;
106
+ }
107
+
108
+ .zoom-controls span {
109
+ font-size: 13px;
110
+ }
111
+ </style>
@@ -47,22 +47,39 @@
47
47
  </div>
48
48
  <div v-if="show" class="preview">
49
49
  <div class="toolbar">
50
+
50
51
  <div class="icon-toolbar" v-print="'#printMe'">
51
52
  <i class="fas fa-print"></i>
52
53
  </div>
54
+ <div v-if="loadingFile" class="icon-toolbar">
55
+ <i class="fa-duotone fa-solid fa-spinner-third loading-icon"></i>
56
+ </div>
57
+ <div v-else @click="generatePDF" class="icon-toolbar">
58
+ <i class="fa-solid fa-file-pdf"></i>
59
+ </div>
53
60
  <div class="icon-toolbar icon-excel">
54
61
  <ExportExcel :nameFile="name" :header="dataConditional" :data="data" />
55
62
  </div>
63
+ <div class="div-pipe icon-toolbar"></div>
64
+ <div class="icon-toolbar" @click="addEvent({ name: 'zoomIn' })">
65
+ <i class="fa-regular fa-magnifying-glass-plus"></i>
66
+ </div>
67
+
68
+ <div class="icon-toolbar" @click="addEvent({ name: 'zoomOut' })">
69
+ <i class="fa-regular fa-magnifying-glass-minus"></i>
70
+ </div>
56
71
  </div>
57
72
  <ScrollBar :minHeight="400" :maxHeight="820">
58
73
  <br />
59
74
  <div id="printMe" :style="'min-height:' + minHeight + 'px'" class="a4 footer">
60
- <HeaderReport :title="name" />
61
- <div>
62
- <span>Total de <b> {{ totalRecords }}</b> registro(s) </span>
63
- </div>
64
- <ReportTable :header="dataConditional" :data="data" />
65
- <Totalization :totalization="totalization" />
75
+ <Zoom>
76
+ <HeaderReport :title="name" />
77
+ <div>
78
+ <span>Total de <b> {{ totalRecords }}</b> registro(s) </span>
79
+ </div>
80
+ <ReportTable :header="dataConditional" :data="data" />
81
+ <Totalization :totalization="totalization" />
82
+ </Zoom>
66
83
  </div>
67
84
  </ScrollBar>
68
85
  </div>
@@ -88,8 +105,10 @@ import Button from "@nixweb/nixloc-ui/src/component/forms/Button";
88
105
  import Fields from "@nixweb/nixloc-ui/src/component/report/Fields.vue";
89
106
  import Panel from "@nixweb/nixloc-ui/src/component/layout/Panel.vue";
90
107
  import Alert from "@nixweb/nixloc-ui/src/component/layout/Alert";
108
+ import Zoom from "@nixweb/nixloc-ui/src/component/layout/Zoom";
91
109
 
92
110
  import print from "vue-print-nb";
111
+ import html2pdf from 'html2pdf.js'
93
112
 
94
113
  import { mapMutations, mapActions, mapGetters } from "vuex";
95
114
 
@@ -99,7 +118,7 @@ export default {
99
118
  print,
100
119
  },
101
120
  props: ["name", "module", "urlGet", "header", "filters", "minHeight"],
102
- components: { ScrollBar, HeaderReport, Alert, ExportExcel, ReportTable, Molded, FilterQuery, Button, Fields, Panel, Loading, Totalization, ProgressBar },
121
+ components: { ScrollBar, HeaderReport, Alert, Zoom, ExportExcel, ReportTable, Molded, FilterQuery, Button, Fields, Panel, Loading, Totalization, ProgressBar },
103
122
  data() {
104
123
  return {
105
124
  loading: false,
@@ -113,6 +132,7 @@ export default {
113
132
  totalPerPage: 50,
114
133
  pagination: [],
115
134
  cancel: false,
135
+ loadingFile: false,
116
136
  }
117
137
  },
118
138
  mounted() {
@@ -144,7 +164,7 @@ export default {
144
164
  }
145
165
  },
146
166
  methods: {
147
- ...mapMutations("generic", ["removeLoading"]),
167
+ ...mapMutations("generic", ["addEvent", "removeLoading"]),
148
168
  ...mapActions("generic", ["getApi"]),
149
169
  executeSearch() {
150
170
  this.cancel = false;
@@ -205,6 +225,31 @@ export default {
205
225
  });
206
226
  }
207
227
  },
228
+ async generatePDF() {
229
+ try {
230
+ this.loadingFile = true;
231
+
232
+ const element = document.getElementById('printMe');
233
+
234
+ const opt = {
235
+ margin: 0,
236
+ filename: this.name + '.pdf',
237
+ image: { type: 'jpeg', quality: 0.98 },
238
+ html2canvas: { scale: 2 },
239
+ jsPDF: { unit: 'mm', format: 'a4', orientation: 'landscape' }
240
+ };
241
+
242
+ await html2pdf()
243
+ .set(opt)
244
+ .from(element)
245
+ .save();
246
+
247
+ } catch (error) {
248
+ console.error('Erro ao gerar PDF:', error);
249
+ } finally {
250
+ this.loadingFile = false;
251
+ }
252
+ },
208
253
  verifyIfPagination() {
209
254
  if (this.pagination.length > 0) {
210
255
  this.currentPage++;
@@ -255,6 +300,13 @@ export default {
255
300
  margin-bottom: 30px;
256
301
  }
257
302
 
303
+ .div-pipe {
304
+ border-left: 1.5px solid rgb(189, 189, 189);
305
+ margin: 0px -15px -6px 0px;
306
+ height: 25px;
307
+ }
308
+
309
+
258
310
  .preview {
259
311
  background-color: #fafafa;
260
312
  padding-bottom: 20px;
@@ -262,6 +314,18 @@ export default {
262
314
  height: 100%;
263
315
  }
264
316
 
317
+ .loading-icon {
318
+ color: orange;
319
+ font-size: 19px;
320
+ animation: spin 1s linear infinite;
321
+ }
322
+
323
+ @keyframes spin {
324
+ 100% {
325
+ transform: rotate(360deg);
326
+ }
327
+ }
328
+
265
329
  .toolbar {
266
330
  height: 40px;
267
331
  border-bottom: 1px hsl(0, 0%, 82.7%) solid;
@@ -4,6 +4,12 @@
4
4
  <div class="icon-toolbar" v-print="'#printMeSub'">
5
5
  <i class="fas fa-print"></i>
6
6
  </div>
7
+ <div v-if="loadingFile" class="icon-toolbar">
8
+ <i class="fa-duotone fa-solid fa-spinner-third loading-icon"></i>
9
+ </div>
10
+ <div v-else @click="generatePDF" class="icon-toolbar">
11
+ <i class="fa-solid fa-file-pdf"></i>
12
+ </div>
7
13
  <div class="icon-toolbar icon-excel">
8
14
  <ExportExcel :nameFile="name" :header="header" :data="data" />
9
15
  </div>
@@ -67,7 +73,9 @@ import ScrollBar from "@nixweb/nixloc-ui/src/component/layout/ScrollBar.vue";
67
73
  import HeaderReport from "../shared/HeaderReport.vue";
68
74
  import TotalizationReport from "../shared/TotalizationReport.vue";
69
75
  import ExportExcel from "@nixweb/nixloc-ui/src/component/shared/ExportExcel";
76
+
70
77
  import print from "vue-print-nb";
78
+ import html2pdf from 'html2pdf.js'
71
79
 
72
80
  import { mapMutations } from "vuex";
73
81
 
@@ -77,6 +85,11 @@ export default {
77
85
  },
78
86
  props: ["name", "titleHeader", "header", "data", "totalization", "totalizationCustom", "minHeight"],
79
87
  components: { ScrollBar, HeaderReport, TotalizationReport, ExportExcel },
88
+ data() {
89
+ return {
90
+ loadingFile: false,
91
+ }
92
+ },
80
93
  methods: {
81
94
  ...mapMutations("generic", ["addEvent"]),
82
95
  convertClass(fieldComparison, classCssBody) {
@@ -96,6 +109,31 @@ export default {
96
109
  sendEvent(eventName, data) {
97
110
  if (eventName) this.addEvent({ name: eventName, data: data });
98
111
  },
112
+ async generatePDF() {
113
+ try {
114
+ this.loadingFile = true;
115
+
116
+ const element = document.getElementById('printMeSub');
117
+
118
+ const opt = {
119
+ margin: 0,
120
+ filename: this.name + '.pdf',
121
+ image: { type: 'jpeg', quality: 0.98 },
122
+ html2canvas: { scale: 2 },
123
+ jsPDF: { unit: 'mm', format: 'a4', orientation: 'landscape' }
124
+ };
125
+
126
+ await html2pdf()
127
+ .set(opt)
128
+ .from(element)
129
+ .save();
130
+
131
+ } catch (error) {
132
+ console.error('Erro ao gerar PDF:', error);
133
+ } finally {
134
+ this.loadingFile = false;
135
+ }
136
+ },
99
137
  },
100
138
  };
101
139
  </script>
@@ -150,6 +188,18 @@ table tbody tr td {
150
188
  border: 1px solid #e4e6ec;
151
189
  }
152
190
 
191
+ .loading-icon {
192
+ color: orange;
193
+ font-size: 19px;
194
+ animation: spin 1s linear infinite;
195
+ }
196
+
197
+ @keyframes spin {
198
+ 100% {
199
+ transform: rotate(360deg);
200
+ }
201
+ }
202
+
153
203
  .toolbar {
154
204
  height: 40px;
155
205
  border-bottom: 1px hsl(0, 0%, 82.7%) solid;