vue-intergrall-plugins 0.0.5 → 0.0.9

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": "vue-intergrall-plugins",
3
- "version": "0.0.5",
3
+ "version": "0.0.9",
4
4
  "description": "",
5
5
  "main": "dist/vue-intergrall-plugins.ssr.js",
6
6
  "browser": "dist/vue-intergrall-plugins.esm.js",
@@ -0,0 +1,257 @@
1
+ <template>
2
+ <span class="text-footer-actions--btn" :class="{'files-activated' : openFiles || file.length}" @click="fileSettings.multiple ? openSelectFileHandler('both') : toggleFiles">
3
+ <transition name="fade">
4
+ <span v-if="file.length" class="files-counter" v-text="file.length" @click.stop="toggleFilePreview" :title="dictionary.msg_abrir_anexos"></span>
5
+ </transition>
6
+ <fa-icon :icon="['fas', 'paperclip']" :title="dictionary.title_selecionar_anexo" />
7
+ <transition name="show">
8
+ <div v-if="openFiles" class="text-footer-files-container" :class="{'horizontal' : cssStyle.outsideButtons}">
9
+ <div class="files-btn images" :class="{'margin-bottom' : cssStyle.outsideButtons}" :title="dictionary.title_anexo_img" @click="openSelectFileHandler('img')">
10
+ <fa-icon :icon="['fas', 'image']" />
11
+ </div>
12
+ <div class="files-btn docs" :title="dictionary.title_anexo_doc" @click="openSelectFileHandler('doc')">
13
+ <fa-icon :icon="['fas', 'file-alt']" />
14
+ </div>
15
+ </div>
16
+ </transition>
17
+ <div class="files-pointers d-none">
18
+ <input v-if="fileSettings.multiple" type="file" :id="`both-${textId}`" accept="image/*,application/*" multiple @change="fileUpload($event, 'both')" />
19
+ <input v-if="!fileSettings.multiple" type="file" :id="`img-${textId}`" accept="image/*" @change="fileUpload($event, 'img')" />
20
+ <input v-if="!fileSettings.multiple" type="file" :id="`doc-${textId}`" accept="application/*" @change="fileUpload($event, 'doc')" />
21
+ </div>
22
+ <transition name="fade">
23
+ <div class="text-footer-preview-container" @click.stop v-show="showFilePreview" :class="[previewContainerClass]">
24
+ <SingleFilePreview
25
+ v-if="!fileSettings.multiple"
26
+ :dictionary="dictionary"
27
+ :file="file"
28
+ :isDoc="isDoc"
29
+ :fileFormatError="fileFormatError"
30
+ :validFileFormats="validFileFormats"
31
+ :imagePreview="imagePreview"
32
+ @delete-file="deleteFile"
33
+ @open-image="openImage"
34
+ />
35
+ <MultipleFilePreview
36
+ v-else
37
+ :dictionary="dictionary"
38
+ :file="file"
39
+ :fileFormatError="fileFormatError"
40
+ :validFileFormats="validFileFormats"
41
+ @delete-file="deleteFile"
42
+ @delete-specific-file="deleteSpecificFile"
43
+ @open-image="openImage"
44
+ />
45
+ </div>
46
+ </transition>
47
+ </span>
48
+ </template>
49
+
50
+ <style>
51
+ .fade-enter-active,
52
+ .fade-leave-active {
53
+ transition: opacity 0.3s;
54
+ }
55
+ .fade-enter,
56
+ .fade-leave-to {
57
+ opacity: 0;
58
+ }
59
+
60
+ .files-counter {
61
+ position: absolute;
62
+ top: 0px;
63
+ z-index: 1;
64
+ right: 0px;
65
+ font-size: .5rem;
66
+ width: 15px;
67
+ height: 15px;
68
+ border-radius: 50%;
69
+ background: #a4ac86;
70
+ display: flex;
71
+ justify-content: center;
72
+ align-items: center;
73
+ cursor: pointer;
74
+ opacity: .9;
75
+ transition: all 300ms;
76
+ color: #FFF;
77
+ font-weight: 900;
78
+ }
79
+ .files-counter:hover {
80
+ opacity: 1
81
+ }
82
+ </style>
83
+
84
+ <script>
85
+ import SingleFilePreview from "./SingleFilePreview"
86
+ import MultipleFilePreview from "./MultipleFilePreview"
87
+
88
+ export default {
89
+ components: { SingleFilePreview, MultipleFilePreview },
90
+ props: {
91
+ textId: {
92
+ type: String,
93
+ required: true
94
+ },
95
+ dictionary: {
96
+ type: Object,
97
+ required: true
98
+ },
99
+ fileSettings: {
100
+ type: Object,
101
+ required: false
102
+ },
103
+ cssStyle: {
104
+ type: Object,
105
+ required: false
106
+ }
107
+ },
108
+ data() {
109
+ return {
110
+ file: [],
111
+ openFiles: false,
112
+ showFilePreview: false,
113
+ imagePreview: "",
114
+ isDoc: false,
115
+ fileFormatError: false,
116
+ validFileFormats: ""
117
+ }
118
+ },
119
+ computed: {
120
+ previewContainerClass() {
121
+ if(this.fileFormatError) return "isError"
122
+ if(this.fileSettings.multiple) return "isMultiple"
123
+ if(this.isDoc) return "isDoc"
124
+ return "isMsg"
125
+ }
126
+ },
127
+ methods: {
128
+ toggleFiles() {
129
+ this.openFiles = !this.openFiles
130
+ },
131
+ openSelectFileHandler(type) {
132
+ const fileInput = document.querySelector(`#${type}-${this.textId}`)
133
+ if(fileInput) fileInput.click()
134
+ if(!fileInput) if (!document.querySelector(".toasted.toasted-primary.error")) this.$toasted.global.defaultError()
135
+ },
136
+ isFileValid(type, fileName) {
137
+ const extensions = type === "img" ? this.fileSettings.imagesExtensions : this.fileSettings.docsExtensions
138
+ const regex = new RegExp("("+extensions+")", "i")
139
+
140
+ if(regex.test(fileName)) return true
141
+ this.showToastedValidFormats()
142
+ return false
143
+ },
144
+ showToastedValidFormats() {
145
+ if (!document.querySelector(".toasted.toasted-primary.error")) this.$toasted.global.defaultError({ msg: this.dictionary.msg_formato_invalido })
146
+ const str = {
147
+ img: this.fileSettings.imagesExtensions.split("|").join(", "),
148
+ doc: this.fileSettings.docsExtensions.split("|").join(", ")
149
+ }
150
+ if (!document.querySelector(".toasted.toasted-primary.info")) this.$toasted.global.showValidFormats({ msg: `Imagens: ${str.img} - Documentos: ${str.doc} ${this.dictionary.msg_extensoes_aceitas}` })
151
+ },
152
+ fileUpload(event, type, externalCall) {
153
+ try {
154
+ this.openFiles = false
155
+ let filesAux = !externalCall ? event.target.files ? event.target.files : event.dataTransfer.files : event
156
+ this.file = filesAux.length ? filesAux : this.file
157
+
158
+ if(!this.file.length) return
159
+ if(!this.fileSettings.multiple) {
160
+ this.file = this.file[0]
161
+ this.singleFileUpload(type, this.file.name)
162
+ }else {
163
+ this.multipleFileUpload()
164
+ }
165
+ }catch(e) {
166
+ console.error("Error file upload")
167
+ console.error(e)
168
+ }
169
+ },
170
+ returnFileType(file) {
171
+ const imgRegex = new RegExp("\.("+this.fileSettings.imagesExtensions+")", "i")
172
+ if(imgRegex.test(file.name)) return "img"
173
+
174
+ const docRegex = new RegExp("\.("+this.fileSettings.docsExtensions+")", "i")
175
+ if(docRegex.test(file.name)) return "doc"
176
+
177
+ return ""
178
+ },
179
+ multipleFileUpload() {
180
+ let waitForImageLoad = false
181
+ this.file = Array.from(this.file)
182
+ this.file.forEach(file => {
183
+ const fileReader = new FileReader();
184
+
185
+ const singleFileType = this.returnFileType(file)
186
+ if(!singleFileType) file.invalid = true
187
+ file.imgOrDoc = singleFileType ? singleFileType : ""
188
+
189
+ if(file.imgOrDoc === "doc") this.isDoc = true
190
+ if(file.imgOrDoc === "img") {
191
+ waitForImageLoad = true
192
+ fileReader.onload = () => file.src = fileReader.result
193
+ fileReader.onloadend = () => this.emitFileVars(true)
194
+ }
195
+
196
+ if(this.isFileValid(file.imgOrDoc, file.name)) {
197
+ if(file.imgOrDoc === "img") fileReader.readAsDataURL(file)
198
+ }else{
199
+ file.invalid = true
200
+ this.fileFormatError = true
201
+ this.validFileFormats = `${file.imgOrDoc === "img" ? this.fileSettings.imagesExtensions.split("|").join(", ") : this.fileSettings.docsExtensions.split("|").join(", ")} ${this.dictionary.msg_extensoes_aceitas}`
202
+ }
203
+ })
204
+
205
+ if(this.isDoc && !waitForImageLoad) this.emitFileVars()
206
+ },
207
+ singleFileUpload(type, fileName) {
208
+ const fileReader = new FileReader()
209
+ if(type === "img") {
210
+ fileReader.onload = () => this.imagePreview = fileReader.result
211
+ fileReader.onloadend = () => this.emitFileVars()
212
+ }
213
+
214
+ if(this.isFileValid(type, fileName)) {
215
+ if(type === "img") fileReader.readAsDataURL(this.file)
216
+ if(type === "doc") this.isDoc = true
217
+
218
+ this.fileFormatError = false
219
+ }else {
220
+ this.fileFormatError = true
221
+ this.validFileFormats = `${type === "img" ? this.fileSettings.imagesExtensions.split("|").join(", ") : this.fileSettings.docsExtensions.split("|").join(", ")} ${this.dictionary.msg_extensoes_aceitas}`
222
+ }
223
+
224
+ if(this.isDoc) this.emitFileVars()
225
+ },
226
+ toggleFilePreview() {
227
+ this.showFilePreview = !this.showFilePreview
228
+ },
229
+ emitFileVars() {
230
+ const vars = { file: this.file, isDoc: this.isDoc, showFilePreview: this.showFilePreview, imagePreview: this.imagePreview, fileFormatError: this.fileFormatError }
231
+
232
+ this.$emit("set-file-vars", vars)
233
+ this.$parent.focusTextarea()
234
+ },
235
+ deleteSpecificFile(obj) {
236
+ const { fileName } = obj
237
+ this.file = this.file.filter(file => {
238
+ return file.name != fileName
239
+ })
240
+ this.file.length ? this.emitFileVars(true) : this.deleteFile()
241
+ },
242
+ deleteFile() {
243
+ this.$emit("set-file-vars", { file: [], isDoc: false, showFilePreview: false, imagePreview: "", fileFormatError: false })
244
+
245
+ this.file = []
246
+ this.isDoc = false
247
+ this.showFilePreview = false
248
+ this.imagePreview = ""
249
+ this.fileFormatError = false
250
+ this.validFileFormats = ""
251
+ },
252
+ openImage(imagePreview) {
253
+ this.$emit("open-image", !imagePreview ? this.imagePreview : imagePreview)
254
+ }
255
+ }
256
+ }
257
+ </script>
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <span class="text-footer-actions--btn" :class="{'audio-activated' : isRecording}" @click="toggleAudioRecorder">
3
+ <fa-icon :icon="['fas', 'microphone']" />
4
+ </span>
5
+ </template>
6
+
7
+ <script>
8
+ export default {
9
+ props: {
10
+ dictionary: {
11
+ type: Object,
12
+ required: true
13
+ }
14
+ },
15
+ data() {
16
+ return {
17
+ isRecording: false,
18
+ mediaRecorder: {}
19
+ }
20
+ },
21
+ methods: {
22
+ toggleAudioRecorder() {
23
+ if(!this.mediaRecorder.state) return this.initAudioRecorder()
24
+
25
+ this.isRecording = !this.isRecording
26
+
27
+ if(this.isRecording) return this.mediaRecorder.start()
28
+ return this.mediaRecorder.stop()
29
+ },
30
+ initAudioRecorder() {
31
+ navigator.mediaDevices.getUserMedia({ audio: true })
32
+ .then(stream => {
33
+ this.mediaRecorder = new MediaRecorder(stream)
34
+ const audioChunks = []
35
+ this.mediaRecorder.ondataavailable = eventData => { audioChunks.push(eventData.data) }
36
+ this.mediaRecorder.onstop = () => {
37
+ const blob = new Blob(audioChunks, { type: "audio/mpeg" })
38
+ blob.lastModifiedDate = new Date()
39
+ blob.name = `im-audio-file-${parseInt(Math.random() * 50000)}`
40
+ const reader = new FileReader()
41
+ reader.readAsDataURL(blob)
42
+ reader.onloadend = () => {
43
+ this.$emit("set-audio", { audioFile: new File([blob], `${blob.name}.mpeg`, { type: blob.type }), audioSource: reader.result })
44
+ }
45
+ stream.getTracks().forEach(track => track.stop())
46
+ }
47
+
48
+ this.toggleAudioRecorder()
49
+ },
50
+ error => {
51
+ this.$toasted.global.defaultError({ msg: this.dictionary.msg_permitir_audio })
52
+ console.error("error audio recorder: ", error)
53
+ })
54
+ },
55
+ deleteMediaRecorder() {
56
+ this.mediaRecorder = {}
57
+ }
58
+ }
59
+ }
60
+ </script>
@@ -0,0 +1,197 @@
1
+ <template>
2
+ <div class="multiple-file-preview">
3
+ <transition-group name="fade">
4
+ <Loader v-if="loading" key="mfp-loader" />
5
+ <template v-else-if="fileFormatError">
6
+ <span @click="deleteFile" :title="dictionary.msg_cancelar_anexo" class="text-footer-exclude-file" key="mfp-exlude-file">
7
+ <fa-icon :icon="['fas', 'times-circle']" />
8
+ </span>
9
+ <div class="text-footer-invalid-format" v-if="fileFormatError" key="mfp-invalid-format">
10
+ <h3 v-text="dictionary.titulo_msg_formato_invalido"></h3>
11
+ <h4 v-text="validFileFormats"></h4>
12
+ </div>
13
+ </template>
14
+ <template v-else>
15
+ <div class="file-preview" v-for="(singleFile, index) in file" :key="index">
16
+ <p class="file-title">
17
+ <fa-icon :icon="icon(singleFile.imgOrDoc)" />
18
+ {{ singleFile.name }}
19
+ </p>
20
+ <p v-if="singleFile.invalid" class="file-title red">
21
+ {{ dictionary.titulo_msg_formato_invalido ? dictionary.titulo_msg_formato_invalido : "Arquivo invalido" }}
22
+ </p>
23
+ <div class="small-img">
24
+ <span class="img-container" v-if="singleFile.imgOrDoc === 'img'">
25
+ <img
26
+ :src="singleFile.src"
27
+ :alt="dictionary.alt_previa_img"
28
+ @click="openImage(singleFile.src)"
29
+ />
30
+ </span>
31
+ <span class="pdf" v-else-if="isPdf(singleFile.type)">
32
+ <fa-icon :icon="['fas', 'file-pdf']" />
33
+ </span>
34
+ </div>
35
+ <span @click="deleteSpecificFile(singleFile.name, index)" :title="dictionary.msg_excluir_anexo" class="delete-file">
36
+ <fa-icon :icon="['fas', 'times-circle']" />
37
+ </span>
38
+ </div>
39
+ </template>
40
+ </transition-group>
41
+ </div>
42
+ </template>
43
+
44
+ <script>
45
+ import Loader from "../Loader/Loader"
46
+
47
+ export default {
48
+ components: { Loader },
49
+ data() {
50
+ return {
51
+ loading: true,
52
+ loadingTimeout: 0,
53
+ ignoreNextUpdate: false
54
+ }
55
+ },
56
+ mounted() {
57
+ setTimeout(() => { this.loading = false;}, 500);
58
+ },
59
+ watch: {
60
+ file() {
61
+ if(!this.ignoreNextUpdate) {
62
+ if(this.loadingTimeout) clearTimeout(this.loadingTimeout);
63
+ this.loading = true;
64
+ this.loadingTimeout = setTimeout(() => { this.loading = false; }, 500);
65
+ this.ignoreNextUpdate = true
66
+ }
67
+ this.ignoreNextUpdate = false;
68
+ }
69
+ },
70
+ props: {
71
+ dictionary: { type: Object, required: true },
72
+ file: { type: Array, required: true },
73
+ fileFormatError: { type: Boolean, required: false },
74
+ validFileFormats: { type: String, required: false, default: "" }
75
+ },
76
+ methods: {
77
+ deleteFile() {
78
+ this.$emit("delete-file");
79
+ },
80
+ deleteSpecificFile(fileName, index) {
81
+ this.ignoreNextUpdate = true;
82
+ this.$emit("delete-specific-file", { fileName, index });
83
+ },
84
+ openImage(image) {
85
+ this.$emit("open-image", image);
86
+ },
87
+ icon(imgOrDoc) {
88
+ if(!imgOrDoc) return ['fas', 'times-circle'];
89
+ return imgOrDoc == 'doc' ? ['fas', 'file-alt'] : ['fas', 'image'];
90
+ },
91
+ isPdf(type) {
92
+ return type === "application/pdf" ? true : false
93
+ }
94
+ }
95
+ }
96
+ </script>
97
+
98
+ <style>
99
+ .multiple-file-preview {
100
+ position: relative;
101
+ display: flex;
102
+ flex-direction: column;
103
+ width: 100%;
104
+ height: 100%;
105
+ max-height: 100%;
106
+ overflow-y: auto;
107
+ overflow-x: hidden;
108
+ border-top-left-radius: 2.5px;
109
+ border-top-right-radius: 2.5px;
110
+ transition: background-color 150ms;
111
+ }
112
+
113
+ .file-preview {
114
+ display: flex;
115
+ width: 100%;
116
+ align-items: center;
117
+ padding: 5px 10px;
118
+ transition: background-color 150ms;
119
+ }
120
+ .file-preview:hover {
121
+ background-color: rgba(0, 0, 0, .1)
122
+ }
123
+
124
+ .file-title {
125
+ color: #222;
126
+ display: flex;
127
+ align-items: center;
128
+ white-space: nowrap;
129
+ text-overflow: ellipsis;
130
+ overflow: hidden;
131
+ padding: 4px 10px;
132
+ background-color: rgba(255, 255, 255, 0.8);
133
+ border-radius: 30px;
134
+ }
135
+ .file-title.red {
136
+ color: #E74C3C;
137
+ margin-left:5px;
138
+ }
139
+ .file-title > svg {
140
+ margin-right: 5px
141
+ }
142
+
143
+ .small-img {
144
+ flex: 1;
145
+ margin: 0 15px;
146
+ display: flex;
147
+ justify-content: center;
148
+ align-items: center;
149
+ position: relative;
150
+ }
151
+ .small-img img {
152
+ height: 40px;
153
+ cursor: pointer;
154
+ }
155
+ .small-img .pdf {
156
+ display: flex;
157
+ justify-content: center;
158
+ align-items: center;
159
+ font-size: 30px;
160
+ color: #E74C3C;
161
+ }
162
+ .small-img .pdf svg{
163
+ z-index: 1;
164
+ }
165
+ .small-img .pdf::after {
166
+ content: "";
167
+ position: absolute;
168
+ bottom: 2px;
169
+ transform: translateY(2px);
170
+ width: 20px;
171
+ height: 20px;
172
+ background-color: #FFF;
173
+ }
174
+ .img-container {
175
+ padding: 5px;
176
+ border-radius: 2.5px;
177
+ background-color: rgba(0, 0, 0, .15);
178
+ display: flex;
179
+ justify-content: center;
180
+ align-items: center;
181
+ }
182
+
183
+ .delete-file {
184
+ display: flex;
185
+ justify-content: center;
186
+ align-items: center;
187
+ border-radius: 50%;
188
+ background-color: #FFF;
189
+ min-width: 1rem;
190
+ min-height: 1rem;
191
+ cursor: pointer;
192
+ }
193
+ .delete-file > svg {
194
+ font-size: 1rem;
195
+ color: #E74C3C;
196
+ }
197
+ </style>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <span
3
+ class="max-characters no-width"
4
+ v-if="maxCharacters"
5
+ v-text="`(${this.remainingCharacters})`"
6
+ ></span>
7
+ </template>
8
+
9
+ <script>
10
+ export default {
11
+ props: {
12
+ message: {
13
+ type: String,
14
+ required: true
15
+ },
16
+ maxCharacters: {
17
+ type: Number,
18
+ required: false
19
+ },
20
+ },
21
+ computed: {
22
+ remainingCharacters() {
23
+ if(this.message.length) return this.maxCharacters - this.message.length
24
+ return this.maxCharacters
25
+ }
26
+ }
27
+ }
28
+ </script>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <div class="single-file-preview">
3
+ <span @click="deleteFile" :title="dictionary.msg_cancelar_anexo" class="text-footer-exclude-file">
4
+ <fa-icon :icon="['fas', 'times-circle']" />
5
+ </span>
6
+ <div class="text-footer-invalid-format" v-if="fileFormatError">
7
+ <h3 v-text="dictionary.titulo_msg_formato_invalido"></h3>
8
+ <h4 v-text="validFileFormats"></h4>
9
+ </div>
10
+ <template v-else>
11
+ <h3 v-if="file.name" class="text-footer-preview-title">
12
+ <fa-icon :icon="['fas', 'file-alt']" v-if="isDoc" />
13
+ <fa-icon :icon="['fas', 'image']" v-else />
14
+ {{ file.name }}
15
+ </h3>
16
+ <div class="text-footer-image-preview" v-if="imagePreview">
17
+ <img :src="imagePreview" :alt="dictionary.alt_previa_img" @click="openImage">
18
+ </div>
19
+ </template>
20
+ </div>
21
+ </template>
22
+
23
+ <script>
24
+ export default {
25
+ props: {
26
+ dictionary: { type: Object, required: true },
27
+ file: { type: File, required: true },
28
+ isDoc: { type: Boolean, required: false },
29
+ fileFormatError: { type: Boolean, required: false },
30
+ validFileFormats: { type: String, required: false, default: "" },
31
+ imagePreview: { type: String, required: false }
32
+ },
33
+ methods: {
34
+ deleteFile() {
35
+ this.$emit("delete-file")
36
+ },
37
+ openImage() {
38
+ this.$emit("open-image")
39
+ }
40
+ }
41
+ }
42
+ </script>
43
+
44
+ <style>
45
+
46
+ </style>