@nixweb/nixloc-ui 0.0.209 → 0.0.211

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.209",
3
+ "version": "0.0.211",
4
4
  "description": "Componentes UI",
5
5
  "author": "Fábio Ávila <fabio@nixweb.com.br>",
6
6
  "private": false,
@@ -24,6 +24,7 @@ export default {
24
24
  required: Boolean,
25
25
  initialValue: Array,
26
26
  value: Array,
27
+ change: Function
27
28
  },
28
29
  data() {
29
30
  return {
@@ -39,10 +40,12 @@ export default {
39
40
  if (this.newItem) {
40
41
  this.tos.push(this.newItem);
41
42
  this.newItem = "";
43
+ this.change();
42
44
  }
43
45
  },
44
46
  removeEmail(index) {
45
47
  this.tos.splice(index, 1);
48
+ this.change();
46
49
  }
47
50
  },
48
51
  watch: {
@@ -1,10 +1,12 @@
1
1
  <template>
2
2
  <div>
3
+ <Alert v-if="!success" type="danger">
4
+ Não é permitido enviar arquivos com mais de 5 megabytes.
5
+ </Alert>
3
6
  <div v-if="loading">
4
- <span>Aguarde, estamos importando os arquivos...</span>
5
7
  <Loading type="line" :center="false" />
6
8
  </div>
7
- <div v-else>
9
+ <div>
8
10
  <b-row>
9
11
  <b-col sm="3">
10
12
  <div class="file">
@@ -14,65 +16,88 @@
14
16
  </div>
15
17
  <div class="file">
16
18
  <button class="button small primary">
17
- <span><i class="fa-solid fa-upload"></i> Carregar arquivos</span>
19
+ <span><i class="fa-solid fa-upload"></i> Carregar</span>
18
20
  </button>
19
21
  <input type="file" name="myfile" ref="file" @change="confirm" multiple />
20
22
  </div>
21
23
  </b-col>
22
- <b-col sm="9">
24
+ <b-col sm="9" v-if="!showCapture">
23
25
  <div class="side-by-side" v-for="attachment in attachments">
24
26
  <div class="text-center box-file">
25
- <div v-if="attachment.extension == 'png' || attachment.extension == 'jpg'">
27
+ <div class="div-image" v-if="attachment.extension == '.png' || attachment.extension == '.jpg'"
28
+ @click="openImage(baseUrl + attachment.fileName)">
26
29
  <img class="img" :src="baseUrl + attachment.fileName">
27
30
  </div>
28
31
  <div class="icon-generic" v-else>
29
32
  <i class="fa-light fa-file"></i>
30
33
  <div><span class="name">{{ attachment.name }}</span></div>
31
34
  </div>
32
- <div class="icon side-by-side">
33
- <i class="fa-solid fa-download"></i>
35
+ <div v-if="idSelected != attachment.id">
36
+ <div class="icon side-by-side">
37
+ <a :href="baseUrl + attachment.fileName">
38
+ <i class="fa-solid fa-download"></i>
39
+ </a>
40
+ </div>
41
+ <div class="icon icon-close side-by-side" @click="confirmRemove(attachment.id)">
42
+ <i class="fa-solid fa-circle-xmark"></i>
43
+ </div>
34
44
  </div>
35
- <div class="icon icon-close side-by-side">
36
- <i class="fa-solid fa-circle-xmark"></i>
45
+ <div v-else>
46
+ <div class="icon icon-confirm side-by-side" @click="removeSelected(attachment.id)">
47
+ <i class="fa-solid fa-circle-check"></i>
48
+ </div>
49
+ <div class="icon icon-close side-by-side" @click="cancel()">
50
+ <i class="fa-solid fa-xmark"></i>
51
+ </div>
37
52
  </div>
38
53
  </div>
39
54
  </div>
40
55
  </b-col>
41
56
  </b-row>
42
57
  </div>
43
- <Modal title="Câmera" :width="600" :height="750" v-if="showModal('webcam')" :onHideModal="stopCamera">
58
+ <div v-show="showInModal">
59
+ <Modal title="Câmera" :width="600" :height="750" v-if="showModal('webcam')" :onHideModal="stopCamera">
60
+ <div class="text-center">
61
+ <WebCam ref="webcam" :autoplay="false" width="400" height="100%"></WebCam>
62
+ <br>
63
+ <div class="side-by-side">
64
+ <button class="button primary" @click="captureImage">
65
+ <i class="fa-solid fa-camera"></i>
66
+ Capturar
67
+ </button>
68
+ </div>
69
+ </div>
70
+ </Modal>
71
+ <Modal title="Imagem" :width="800" v-show="showModal('image')">
72
+ <div class="text-center">
73
+ <img class="img-selected" :src="imageSelected">
74
+ </div>
75
+ </Modal>
76
+ </div>
77
+ <div v-if="!showInModal && showCapture">
44
78
  <div class="text-center">
45
79
  <WebCam ref="webcam" :autoplay="false" width="400" height="100%"></WebCam>
46
80
  <br>
47
81
  <div class="side-by-side">
48
- <button class="button primary" @click="captureImage">
82
+ <button class="button small primary" @click="captureImage">
49
83
  <i class="fa-solid fa-camera"></i>
50
84
  Capturar
51
85
  </button>
52
- </div>
53
- </div>
54
- </Modal>
55
- <Modal title="Confirmar" :width="600" :height="750" v-if="showModal('confirm')">
56
- <div class="text-center title">
57
- <div>
58
- Total de <b>{{ files.length }}</b> carregados...
59
- </div>
60
- <div>
61
- <button class="button small primary" @click="loadFiles">
62
- <span>
63
- <i class="fa-solid fa-circle-check"></i> Confirmar
64
- </span>
86
+ <button class="button small danger" @click="stopCamera">
87
+ <i class="fa-solid fa-circle-xmark"></i>
88
+ Fechar
65
89
  </button>
66
90
  </div>
67
91
  </div>
68
-
69
- </Modal>
92
+ </div>
70
93
  </div>
71
94
  </template>
72
95
  <script>
73
96
 
74
97
  import Modal from "@nixweb/nixloc-ui/src/component/forms/Modal";
75
98
  import Loading from "@nixweb/nixloc-ui/src/component/shared/Loading.vue";
99
+ import Confirmation from "@nixweb/nixloc-ui/src/component/shared/Confirmation.vue";
100
+ import Alert from "@nixweb/nixloc-ui/src/component/layout/Alert";
76
101
 
77
102
  import { WebCam } from 'vue-cam-vision'
78
103
 
@@ -82,12 +107,18 @@ export default {
82
107
  components: {
83
108
  WebCam,
84
109
  Modal,
85
- Loading
110
+ Loading,
111
+ Confirmation,
112
+ Alert,
86
113
  },
87
114
  props: {
88
115
  baseUrl: {
89
116
  type: String,
90
- default: "https://espaco.blob.core.windows.net",
117
+ default: "https://espaco.blob.core.windows.net/nixloc-attachments/",
118
+ },
119
+ showInModal: {
120
+ type: Boolean,
121
+ default: true
91
122
  },
92
123
  source: String,
93
124
  genericId: String
@@ -95,29 +126,43 @@ export default {
95
126
  data() {
96
127
  return {
97
128
  urlPost: "/api/v1/adm/attachment/upload",
129
+ urlGet: "/api/v1/adm/attachment/get-all",
130
+ urlDelete: "/api/v1/adm/attachment/delete",
98
131
  files: [],
99
- attachments: [
100
- {
101
- fileName: "T7I300FDB9_3.png",
102
- extension: "png",
103
- },
104
- {
105
- name: "screensh...",
106
- fileName: "T7I300FDB9_3.png",
107
- extension: "txt",
108
- },
109
- ],
132
+ attachments: [],
110
133
  captures: [],
111
134
  imgReport: [],
135
+ idSelected: "",
136
+ imageSelected: "",
112
137
  loading: false,
138
+ success: true,
139
+ showCapture: false,
113
140
  };
114
141
  },
142
+ mounted() {
143
+ this.getAll();
144
+ },
115
145
  methods: {
116
- ...mapMutations("generic", ["openModal", "hideModal"]),
117
- ...mapActions("generic", ["postFileApi", "deleteFileApi"]),
146
+ ...mapMutations("generic", ["openModal", "hideModal", "removeLoading"]),
147
+ ...mapActions("generic", ["postFileApi", "getApi", "deleteAllApi"]),
118
148
  confirm() {
119
149
  this.files = Object.values(this.$refs.file.files);
120
- this.openModal("confirm");
150
+ this.loadFiles();
151
+ },
152
+ confirmRemove(id) {
153
+ this.idSelected = id;
154
+ },
155
+ cancel() {
156
+ this.idSelected = '';
157
+ },
158
+ removeSelected(id) {
159
+ let params = {
160
+ url: this.urlDelete,
161
+ selected: [id],
162
+ };
163
+ this.deleteAllApi(params).then(() => {
164
+ this.getAll();
165
+ });
121
166
  },
122
167
  async loadFiles() {
123
168
  this.hideModal("confirm");
@@ -130,6 +175,7 @@ export default {
130
175
  this.loading = false;
131
176
  },
132
177
  async upload(file) {
178
+ this.loading = true;
133
179
  let params = {
134
180
  url: this.urlPost,
135
181
  file: file,
@@ -137,9 +183,31 @@ export default {
137
183
  container: this.genericId,
138
184
  };
139
185
  const response = await this.postFileApi(params);
186
+ this.success = response.content == "erro" ? false : true;
187
+ this.loading = false;
188
+ let self = this;
189
+ setTimeout(function () {
190
+ self.success = true;
191
+ }, 5000);
192
+ this.getAll();
193
+ },
194
+ getAll() {
195
+ this.idSelected = "";
196
+ this.loading = true;
197
+ let params = { url: this.urlGet, obj: { any: this.source, id: this.genericId } };
198
+ this.getApi(params).then((response) => {
199
+ this.attachments = response.content.data;
200
+ this.loading = false;
201
+ });
202
+ },
203
+ openImage(url) {
204
+ this.openModal("image");
205
+ this.imageSelected = url;
140
206
  },
141
207
  openCamera() {
142
- this.openModal("webcam");
208
+ if (this.showInModal)
209
+ this.openModal("webcam");
210
+ this.showCapture = true;
143
211
  this.startCamera();
144
212
  },
145
213
  startCamera() {
@@ -150,16 +218,58 @@ export default {
150
218
  stopCamera() {
151
219
  if (this.$refs.webcam) {
152
220
  this.$refs.webcam.stop();
153
- this.hideModal();
221
+ this.showCapture = false;
222
+ if (this.showInModal)
223
+ this.hideModal();
154
224
  }
155
225
  },
156
226
  captureImage() {
157
227
  if (this.$refs.webcam) {
158
228
  this.$refs.webcam.capture().then((base64String) => {
159
- console.log(base64String);
229
+ this.upload(this.convertToFile(base64String));
230
+ this.stopCamera();
231
+ this.showCapture = false;
160
232
  });
161
233
  }
162
234
  },
235
+ convertToFile(base64String) {
236
+ const base64Data = base64String.split(',')[1];
237
+ const base64ToByte = (char) => {
238
+ const charCode = char.charCodeAt(0);
239
+
240
+ if (charCode >= 65 && charCode <= 90) {
241
+ return charCode - 65; // A-Z
242
+ } else if (charCode >= 97 && charCode <= 122) {
243
+ return charCode - 71; // a-z
244
+ } else if (charCode >= 48 && charCode <= 57) {
245
+ return charCode + 4; // 0-9
246
+ } else if (charCode === 43) {
247
+ return 62; // +
248
+ } else if (charCode === 47) {
249
+ return 63; // /
250
+ }
251
+
252
+ return 0; // Caracteres inválidos
253
+ };
254
+
255
+ const byteArray = new Uint8Array(base64Data.length / 4 * 3);
256
+ for (let i = 0, j = 0; i < base64Data.length; i += 4, j += 3) {
257
+ const block = (
258
+ (base64ToByte(base64Data[i]) << 18) |
259
+ (base64ToByte(base64Data[i + 1]) << 12) |
260
+ (base64ToByte(base64Data[i + 2]) << 6) |
261
+ base64ToByte(base64Data[i + 3])
262
+ );
263
+
264
+ byteArray[j] = (block >> 16) & 0xff;
265
+ byteArray[j + 1] = (block >> 8) & 0xff;
266
+ byteArray[j + 2] = block & 0xff;
267
+ }
268
+
269
+ const blob = new Blob([byteArray], { type: 'image/png' });
270
+ return new File([blob], "imagem.png", { type: 'image/png' });
271
+
272
+ }
163
273
  },
164
274
  computed: {
165
275
  ...mapGetters("generic", ["showModal"]),
@@ -209,6 +319,11 @@ export default {
209
319
  opacity: 0;
210
320
  }
211
321
 
322
+ .div-image {
323
+ cursor: pointer;
324
+ }
325
+
326
+
212
327
  .small {
213
328
  padding: 3px 8px;
214
329
  font-size: 13px;
@@ -233,27 +348,43 @@ export default {
233
348
  height: 45px;
234
349
  }
235
350
 
351
+ .img-selected {
352
+ width: 80%;
353
+ }
354
+
236
355
  .icon-generic {
237
356
  font-size: 16px;
238
357
  }
239
358
 
240
359
  .name {
241
- font-size: 14px;
360
+ font-size: 12px;
361
+ width: 50px;
362
+ white-space: nowrap;
363
+ text-overflow: ellipsis;
242
364
  }
243
365
 
244
366
  .icon {
245
367
  font-size: 20px;
246
368
  cursor: pointer;
369
+ padding: 5px;
247
370
  }
248
371
 
249
372
  .icon-close {
250
373
  color: red;
251
374
  }
252
375
 
376
+ .icon-confirm {
377
+ color: green;
378
+ }
379
+
253
380
  .title {
254
381
  font-size: 18px;
255
382
  margin-bottom: 20px;
256
383
  }
384
+
385
+ .div-btn {
386
+ margin-bottom: 50px;
387
+ }
257
388
  </style>
258
389
 
259
390