vue-intergrall-plugins 0.0.264 → 0.0.266

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.
@@ -19,7 +19,18 @@
19
19
  </div>
20
20
  <template v-if="selectedTemplate">
21
21
  <div class="tg-component" v-if="selectedTemplate.components">
22
- <TemplateSingle :template="selectedTemplate" @set-vars="setFinalMessage" :hasButton="hasButton" :iconButton="iconButton" @click-trigger="$emit('click-trigger')" :identifier="identifier" :allVariables="allVariables" :dictionary="dictionary" />
22
+ <TemplateSingle
23
+ :key="codTemplate"
24
+ :template="selectedTemplate"
25
+ @set-vars="setFinalMessage"
26
+ @set-file-var="setFileVar"
27
+ :hasButton="hasButton"
28
+ :iconButton="iconButton"
29
+ @click-trigger="$emit('click-trigger')"
30
+ :identifier="identifier"
31
+ :allVariables="allVariables"
32
+ :dictionary="dictionary"
33
+ />
23
34
  </div>
24
35
  <div class="tg-component" v-else>
25
36
  <TemplateMessage @final-message="setMessage" :hasButton="hasButton" :iconButton="iconButton" @click-trigger="$emit('click-trigger', true)" :dictionary="dictionary" />
@@ -84,7 +95,8 @@
84
95
  return {
85
96
  templateOptions: [],
86
97
  codTemplate: {},
87
- selectedTemplate: null
98
+ selectedTemplate: null,
99
+ hasFile: false
88
100
  }
89
101
  },
90
102
  mounted() {
@@ -144,6 +156,7 @@
144
156
  }else{
145
157
  this.selectedTemplate = null
146
158
  }
159
+ // if(this.hasFile) this.setFileVar(false)
147
160
  this.adjustOnSelect()
148
161
  },
149
162
  focusSelect() {
@@ -188,9 +201,9 @@
188
201
  const varName = `{{${keys[keyIndex]}}}`
189
202
  if(message.text.indexOf(varName) != -1) {
190
203
  /**Gerando os obejetos de parametros da notificacao para o component */
191
- if(component.type === "header") {
204
+ if(component.type === "header" && !this.selectedTemplate['parameters'][component.type]) {
192
205
  this.selectedTemplate['parameters'][component.type] = {}
193
- //Header s? pode ter uma vari?vel
206
+ //Header so pode ter uma vari?vel
194
207
  this.selectedTemplate['parameters'][component.type] = {
195
208
  tipo: "text",
196
209
  text: values[keyIndex]
@@ -207,14 +220,25 @@
207
220
  keyIndex++
208
221
  }
209
222
  })
223
+ }else if(component.type == 'header' && component.parameters.seq) {
224
+ if(this.hasFile) {
225
+ if(!this.selectedTemplate['parameters'][component.type]) this.selectedTemplate['parameters'][component.type] = new Array()
226
+ this.selectedTemplate['parameters'][component.type].push({ tipo: 'image', template: component.parameters.seq, link: '' })
227
+ }else {
228
+ delete this.selectedTemplate['parameters'][component.type]
229
+ }
210
230
  }
211
231
  })
212
232
  }
213
233
  }
214
234
  }
215
-
216
235
  this.$emit("template-data", this.selectedTemplate)
217
236
  },
237
+ setFileVar(file) {
238
+ this.hasFile = file ? true : false
239
+ this.$emit("set-file-var", file)
240
+ if(file) this.$emit("template-data", this.selectedTemplate)
241
+ },
218
242
  setMessage(message) {
219
243
  this.$emit("static-message", message)
220
244
  }
@@ -249,6 +273,67 @@ h1, h2, h3, h4, p { margin: 0; padding: 0 }
249
273
  margin-right: 5px;
250
274
  }
251
275
 
276
+ .ts-image-type {
277
+ display: flex;
278
+ align-items: center;
279
+ }
280
+
281
+ .ts-image-type img {
282
+ cursor: pointer;
283
+ }
284
+
285
+ .ts-image-type svg {
286
+ font-size: 25px;
287
+ cursor: pointer;
288
+ }
289
+
290
+ .ts-image-type .select-image {
291
+ color: #838383;
292
+ }
293
+
294
+ .color-red {
295
+ color: #E74C3C;
296
+ }
297
+
298
+ .color-blue {
299
+ color: #007BFF;
300
+ }
301
+
302
+ .color-black {
303
+ color: #333
304
+ }
305
+
306
+ .color-purple {
307
+ color: #a312a3
308
+ }
309
+
310
+ .custom-tooltip-image {
311
+ display: flex;
312
+ justify-content: center;
313
+ align-items: center;
314
+ overflow: visible;
315
+ padding: 5px;
316
+ }
317
+
318
+ .custom-tooltip-image img {
319
+ max-width: 75px;
320
+ max-height: 75px;
321
+ }
322
+
323
+ .ts-button {
324
+ background-color: #FFF;
325
+ border-radius: 10px;
326
+ display: flex;
327
+ justify-content: center;
328
+ align-items: center;
329
+ padding: 3px 15px;
330
+ transition: background-color 150ms ease-in-out;
331
+ }
332
+
333
+ .ts-button:hover {
334
+ background-color: rgb(253, 253, 253);
335
+ }
336
+
252
337
  .tg-select {
253
338
  flex: 1;
254
339
  height: 34px;
@@ -270,9 +355,6 @@ h1, h2, h3, h4, p { margin: 0; padding: 0 }
270
355
  text-overflow: ellipsis;
271
356
  flex: 1;
272
357
  }
273
- .tg-select .vs__selected-options > input {
274
- flex-grow: 0;
275
- }
276
358
 
277
359
  .vs__dropdown-option.vs__dropdown-option--selected {
278
360
  background-color: rgb(26, 95, 173)!important;
@@ -312,10 +394,22 @@ h1, h2, h3, h4, p { margin: 0; padding: 0 }
312
394
  --input-border-default: #007BFF;
313
395
  --input-border-error: #E74C3C;
314
396
  --placeholder-color: #BBB;
397
+ --border-radius: 5px;
315
398
 
316
399
  flex: 2;
317
400
  font-size: .7rem;
318
401
  padding: 10px 0;
402
+ display: flex;
403
+ flex-direction: column;
404
+ }
405
+ .order-1 {
406
+ order: 1
407
+ }
408
+ .custom-box-shadow-bottom {
409
+ box-shadow: 0px 3px 4px -3px rgba(0, 0, 0, .3);
410
+ }
411
+ .custom-border-gray {
412
+ border: 1px solid var(--border-color)!important;
319
413
  }
320
414
  .ts-content header, .ts-content section, .ts-content footer {
321
415
  padding: 3px 5px;
@@ -326,8 +420,8 @@ h1, h2, h3, h4, p { margin: 0; padding: 0 }
326
420
  border-left: 1px solid var(--border-color);
327
421
  }
328
422
  .ts-content header {
329
- border-top-left-radius: 2.5px;
330
- border-top-right-radius: 2.5px;
423
+ border-top-left-radius: var(--border-radius);
424
+ border-top-right-radius: var(--border-radius);
331
425
  border-top: 1px solid var(--border-color);
332
426
  }
333
427
  .ts-content header { font-weight: 550 }
@@ -335,15 +429,15 @@ h1, h2, h3, h4, p { margin: 0; padding: 0 }
335
429
  line-height: 25px;
336
430
  }
337
431
  .ts-content section.margin-bottom {
338
- border-bottom-left-radius: 2.5px;
339
- border-bottom-right-radius: 2.5px;
432
+ border-bottom-left-radius: var(--border-radius);
433
+ border-bottom-right-radius: var(--border-radius);
340
434
  border-bottom: 1px solid var(--border-color);
341
435
  }
342
- .ts-content footer {
436
+ .ts-content footer, .custom-footer-style {
343
437
  border: 1px solid var(--border-color);
344
438
  border-top: unset;
345
- border-bottom-left-radius: 2.5px;
346
- border-bottom-right-radius: 2.5px;
439
+ border-bottom-left-radius: var(--border-radius);
440
+ border-bottom-right-radius: var(--border-radius);
347
441
  }
348
442
  .ts-content input {
349
443
  border: 1px solid transparent;
@@ -468,7 +562,7 @@ h1, h2, h3, h4, p { margin: 0; padding: 0 }
468
562
 
469
563
  .tm-container {
470
564
  border: 1px solid var(--border-color);
471
- border-radius: 2.5px;
565
+ border-radius: 5px;
472
566
  display: flex;
473
567
  }
474
568
 
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="ts-container">
3
3
  <div class="ts-content">
4
- <section :class="{'tm-container' : hasButton}">
4
+ <section :class="{'tm-container custom-box-shadow-bottom' : hasButton}">
5
5
  <TextFooter
6
6
  :textId="'var_1'"
7
7
  width="full"
@@ -1,9 +1,14 @@
1
1
  <template>
2
2
  <div class="ts-container">
3
3
  <div class="ts-content">
4
- <div v-for="(component, cIndex) in template.components" :key="cIndex">
4
+ <div
5
+ v-for="(component, cIndex) in template.components"
6
+ :key="cIndex"
7
+ :class="`${component.type == 'footer' ? 'order-1 custom-box-shadow-bottom' : ''}${template.components.length == 1 ? 'custom-box-shadow-bottom' : ''}`"
8
+ >
5
9
  <header
6
10
  v-if="component.type === 'header'"
11
+ :class="`${template.components.length == 1 ? 'border-radius-5 custom-border-gray' : ''}`"
7
12
  id="template_header"
8
13
  >
9
14
  <div v-for="(param, pIndex) in component.parameters" :key="pIndex">
@@ -19,11 +24,36 @@
19
24
  ></div>
20
25
  <p v-else v-html="param.text"></p>
21
26
  </template>
27
+ <div v-else-if="param.type == 'image'" class="ts-image-type">
28
+ <input class="d-none" type="file" :ref="`ts-input-header-${pIndex}`" :accept="acceptedExtensions" @change="fileUpload($event)" />
29
+ <template v-if="headerFiles[0]">
30
+ <fa-icon
31
+ :icon="['fas', headerFiles[0].current_icon]"
32
+ :class="`color-${headerFiles[0].current_color}`"
33
+ @click="triggerInputFile(`header-${pIndex}`)"
34
+ v-tippy="{placement: 'right'}"
35
+ :content="headerFiles[0].image_preview ?
36
+ `<div class='custom-tooltip-image'>
37
+ <img src='${headerFiles[0].image_preview}' alt='${headerFiles[0].name}' />
38
+ </div>`
39
+ : headerFiles[0].name
40
+ "
41
+ />
42
+ </template>
43
+ <fa-icon
44
+ v-else
45
+ class="select-image"
46
+ :icon="['fas', 'image']"
47
+ @click="triggerInputFile(`header-${pIndex}`)"
48
+ v-tippy="{placement: 'right'}"
49
+ :content="`Selecionar anexo`"
50
+ />
51
+ </div>
22
52
  </div>
23
53
  </header>
24
54
  <section
25
55
  v-if="component.type === 'body'"
26
- :class="{'margin-bottom' : template.components.length === 2 }"
56
+ :class="`${template.components.length == 1 ? 'border-radius-5 custom-border-gray' : ''} ${!hasButtonOrFooterComponent ? 'custom-footer-style custom-box-shadow-bottom custom-border-gray' : ''}`"
27
57
  id="template_body"
28
58
  >
29
59
  <div v-for="(param, pIndex) in component.parameters" :key="pIndex">
@@ -41,8 +71,18 @@
41
71
  </template>
42
72
  </div>
43
73
  </section>
74
+ <section
75
+ v-if="component.type == 'button'"
76
+ :class="`${template.components.length == 1 ? 'border-radius-5 custom-border-gray' : ''} ${!hasFooterComponent ? 'custom-footer-style custom-box-shadow-bottom' : ''}`"
77
+ id="template_buttons"
78
+ >
79
+ <div v-for="(param, pIndex) in component.parameters" :key="pIndex" class="ts-button">
80
+ <p v-if="param.text" v-html="param.text"></p>
81
+ </div>
82
+ </section>
44
83
  <footer
45
84
  v-if="component.type == 'footer'"
85
+ :class="`${template.components.length == 1 ? 'border-radius-5 custom-border-gray' : ''}`"
46
86
  id="template_footer"
47
87
  >
48
88
  <div v-for="(param, pIndex) in component.parameters" :key="pIndex">
@@ -71,7 +111,9 @@ export default {
71
111
  regexVars: /{{var_\d}}/g,
72
112
  lastVar: 0,
73
113
  htmlInputString: `<input type='text' class='input-var input-var-${this.identifier}' autocomplete='off' />`,
74
- varListValues: ""
114
+ varListValues: "",
115
+ acceptedExtensions: "audio/aac, audio/mp4, audio/mpeg, audio/amr, audio/ogg, text/plain, application/pdf, application/vnd.ms-powerpoint, application/msword, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.spreasheetml.sheet, image/jpeg, image/png, video/mp4, video/3gp, image/webp",
116
+ headerFiles: [],
75
117
  };
76
118
  },
77
119
  props: {
@@ -103,12 +145,29 @@ export default {
103
145
  required: true
104
146
  }
105
147
  },
148
+ computed: {
149
+ hasFooterComponent() {
150
+ if(!this.template.components || !this.template.components.length) return false
151
+ const types = []
152
+ this.template.components.forEach(({ type }) => types.push(type))
153
+ if(types.includes('footer')) return true
154
+ return false
155
+ },
156
+ hasButtonOrFooterComponent() {
157
+ if(!this.template.components || !this.template.components.length) return false
158
+ const types = []
159
+ this.template.components.forEach(({ type }) => types.push(type))
160
+ if(types.includes('button')) return true
161
+ return this.hasFooterComponent
162
+ },
163
+ },
106
164
  created() {
107
165
  this.$root.$refs[`template-single-${this.identifier}`] = this
108
166
  },
109
167
  mounted() {
110
168
  if(this.allVariables) this.getListOpts()
111
169
  this.setInputs();
170
+ this.setImageVar(false)
112
171
  },
113
172
  updated() {
114
173
  this.lastVar = 0;
@@ -134,6 +193,7 @@ export default {
134
193
  input.blur();
135
194
  this.setVar({ target: input }, input.id.replace(/[{}]+/g, ''));
136
195
  })
196
+ this.setImageVar(false)
137
197
  },
138
198
  getListOpts() {
139
199
  this.varListValues =
@@ -142,26 +202,112 @@ export default {
142
202
  ${this.allVariables ? '<li> telefone </li>' : ''}
143
203
  </ul>`
144
204
  },
205
+ fileUpload(event) {
206
+ try {
207
+ const allFiles = event.target.files ? event.target.files : event.dataTransfer.files ? event.dataTransfer.files : false
208
+ if(!allFiles || !allFiles.length) return this.setImageVar(false)
209
+ if(allFiles.length > 1) {
210
+ this.$toasted.global.defaultInfo({ msg: `Limite de 1 arquivo por vez` })
211
+ return this.setImageVar(false)
212
+ }
213
+ const file = allFiles[0]
214
+ const { type, name } = file
215
+ const validTypes = ['audio/aac', 'audio/mp4', 'audio/mpeg', 'audio/amr', 'audio/ogg', 'text/plain', 'application/pdf', 'application/vnd.ms-powerpoint', 'application/msword', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.openxmlformats-officedocument.spreasheetml.sheet', 'image/jpeg', 'image/png', 'video/mp4', 'video/3gp', 'image/webp']
216
+ if(!validTypes.includes(type)) {
217
+ this.$toasted.global.defaultInfo({ msg: `(${type}) ${this.dictionary.msg_arquivo_invalido}` })
218
+ return this.setImageVar(false)
219
+ }
220
+ const returnArrType = str => {
221
+ const arr = []
222
+ validTypes.forEach(currentType => {
223
+ if(currentType.indexOf(str) > -1) arr.push(currentType)
224
+ })
225
+ return arr
226
+ }
227
+
228
+ const imageTypes = returnArrType('image/')
229
+ const docTypes = returnArrType('application/')
230
+ const audioTypes = returnArrType('audio/')
231
+ const videoTypes = returnArrType('video/')
232
+ const isPdf = type.indexOf('application/pdf') > -1
233
+
234
+ let sizeInBytes = 0
235
+ Array.from(allFiles).forEach(file => sizeInBytes += file.size)
236
+ const sizeInMb = parseFloat((sizeInBytes / (1024*1024)).toFixed(2))
237
+ if(sizeInMb == 0 && sizeInBytes == 0) {
238
+ this.$toasted.global.defaultInfo({ msg: this.dictionary.msg_arquivo_invalido })
239
+ return this.setImageVar(false)
240
+ }
241
+ const max = imageTypes.includes(type) ? 5 : 15
242
+ if(sizeInMb >= max) {
243
+ this.$toasted.global.defaultInfo({ msg: `Limite de ${max} MB por arquivo` })
244
+ return this.setImageVar(false)
245
+ }
246
+
247
+ const fileReader = new FileReader()
248
+ let current_icon = 'file-alt', current_color = 'blue', setValues = true
249
+ if(imageTypes.includes(type)) {
250
+ setValues = false
251
+ fileReader.readAsDataURL(file)
252
+ fileReader.onload = () => {
253
+ const image_preview = fileReader.result
254
+ current_icon = 'image'
255
+ current_color = 'purple'
256
+ this.headerFiles[0] = { file, image_preview, current_icon, current_color, name }
257
+ this.$forceUpdate()
258
+ this.setImageVar(file)
259
+ }
260
+ }else if(docTypes.includes(type) && isPdf) {
261
+ current_icon = 'file-pdf'
262
+ current_color = 'red'
263
+ }else if(audioTypes.includes(type)) {
264
+ current_icon = 'microphone'
265
+ current_color = 'black'
266
+ }else if(videoTypes.includes(type)) {
267
+ current_icon = 'video',
268
+ current_color = 'black'
269
+ }
270
+
271
+ if(setValues) {
272
+ this.headerFiles[0] = { file, current_icon, current_color, name }
273
+ this.$forceUpdate()
274
+ this.setImageVar(file)
275
+ }
276
+ }catch(error) {
277
+ console.error("Erro file upload: ", error)
278
+ }
279
+ },
280
+ triggerInputFile(origin) {
281
+ if(this.$refs[`ts-input-${origin}`]) {
282
+ const elem = this.$refs[`ts-input-${origin}`][0] ? this.$refs[`ts-input-${origin}`][0] : this.$refs[`ts-input-${origin}`]
283
+ elem && elem.click()
284
+ }
285
+ },
145
286
  setInputs() {
146
287
  let qtdInputs = 0
147
288
  const header = document.querySelector("#template_header");
148
289
  const body = document.querySelector("#template_body");
149
290
  const footer = document.querySelector("#template_footer");
291
+
292
+ let hasText = false
150
293
  if (header !== null) {
151
294
  header.querySelectorAll(`.input-var-${this.identifier}`).forEach((input) => { this.setEvent(input) })
152
295
  qtdInputs += header.querySelectorAll(`.input-var-${this.identifier}`).length
296
+ if(qtdInputs > 0 && header.innerText) hasText = true
153
297
  }
154
298
  if (this.lastVar === 0) this.lastVar += 1
155
299
  if (body !== null) {
156
300
  body.querySelectorAll(`.input-var-${this.identifier}`).forEach((input) => { this.setEvent(input) });
157
301
  qtdInputs += body.querySelectorAll(`.input-var-${this.identifier}`).length
302
+ if(qtdInputs > 0 && body.innerText) hasText = true
158
303
  }
159
304
  if (footer !== null) {
160
305
  footer.querySelectorAll(`.input-var-${this.identifier}`).forEach((input) => { this.setEvent(input) });
161
306
  qtdInputs += footer.querySelectorAll(`.input-var-${this.identifier}`).length
307
+ if(qtdInputs > 0 && footer.innerText) hasText = true
162
308
  }
163
309
 
164
- if(qtdInputs === 1) {
310
+ if(qtdInputs === 1 && !hasText) {
165
311
  document.querySelector(`.input-var-${this.identifier}`).parentElement.style.width = "100%"
166
312
  document.querySelector(`.input-var-${this.identifier}`).style.width = "100%"
167
313
  }else if(qtdInputs === 0) {
@@ -263,6 +409,17 @@ export default {
263
409
 
264
410
  return isValueValid
265
411
  },
412
+ setImageVar(file) {
413
+ this.$emit("set-file-var", file)
414
+ if(!file) {
415
+ this.headerFiles = []
416
+ return this.$forceUpdate()
417
+ }else {
418
+ if(this.lastVar == 0) return this.$emit("set-vars", this.template)
419
+ if(Object.keys(this.varValues).length) return this.$emit("set-vars", this.varValues)
420
+ this.$nextTick(() => this.handleInitialFocus())
421
+ }
422
+ },
266
423
  setVar(event, key, notificar) {
267
424
  if (event && event.target) {
268
425
  key = event.target.id.replace(/[{}]+/g, '')