@testdracul/media-frontend 2.0.0
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/.env.development +4 -0
- package/.env.example +3 -0
- package/.eslintrc.json +25 -0
- package/babel.config.js +5 -0
- package/dist/dracul-media-frontend.es.js +16238 -0
- package/dist/dracul-media-frontend.umd.js +586 -0
- package/dist/media-frontend.css +1 -0
- package/docs-en.md +45 -0
- package/docs-es.md +45 -0
- package/package.json +56 -0
- package/readme.md +36 -0
- package/src/components/CsvWebViewer/CsvWebViewer.vue +81 -0
- package/src/components/CsvWebViewer/index.ts +4 -0
- package/src/components/FileUpload/FileUpload.vue +94 -0
- package/src/components/FileUpload/index.ts +4 -0
- package/src/components/FileUploadButton/FileUploadButton.vue +127 -0
- package/src/components/FileUploadButton/index.ts +4 -0
- package/src/components/FileUploadExpiration/FileUploadExpiration.vue +274 -0
- package/src/components/FileUploadExpiration/index.ts +4 -0
- package/src/components/FileUploadExpress/FileUploadExpress.vue +208 -0
- package/src/components/FileUploadExpress/index.ts +4 -0
- package/src/components/FileView/FileView.vue +336 -0
- package/src/components/FileView/index.ts +4 -0
- package/src/components/GroupsShow/GroupsShow.vue +40 -0
- package/src/components/GroupsShow/index.ts +4 -0
- package/src/components/MediaField/MediaField.vue +62 -0
- package/src/components/MediaField/index.ts +4 -0
- package/src/components/PdfWebViewer/PdfWebViewer.vue +81 -0
- package/src/components/PdfWebViewer/index.ts +4 -0
- package/src/components/UsersShow/UsersShow.vue +39 -0
- package/src/components/UsersShow/index.ts +4 -0
- package/src/components/XlsxWebViewer/XlsxWebViewer.vue +70 -0
- package/src/components/XlsxWebViewer/index.ts +4 -0
- package/src/helpers/redeableBytes.ts +9 -0
- package/src/i18n/index.ts +22 -0
- package/src/i18n/messages/DocMessages.ts +31 -0
- package/src/i18n/messages/ExtraMessages.ts +29 -0
- package/src/i18n/messages/FileMessages.ts +223 -0
- package/src/i18n/messages/UserStorageMessages.ts +145 -0
- package/src/i18n/permissions/FilePermissionMessages.ts +50 -0
- package/src/i18n/permissions/OldPermissionMessages.ts +59 -0
- package/src/i18n/permissions/UserStoragePermissionMessages.ts +40 -0
- package/src/index.ts +70 -0
- package/src/mixins/readableBytesMixin.ts +9 -0
- package/src/pages/FileManagementPage/FileCreate/FileCreate.vue +108 -0
- package/src/pages/FileManagementPage/FileCreate/index.ts +3 -0
- package/src/pages/FileManagementPage/FileCrud/FileCrud.vue +133 -0
- package/src/pages/FileManagementPage/FileCrud/index.ts +4 -0
- package/src/pages/FileManagementPage/FileDelete/FileDelete.vue +61 -0
- package/src/pages/FileManagementPage/FileDelete/index.ts +3 -0
- package/src/pages/FileManagementPage/FileFilters/FileFilters.vue +150 -0
- package/src/pages/FileManagementPage/FileFilters/index.ts +3 -0
- package/src/pages/FileManagementPage/FileForm/FileForm.vue +184 -0
- package/src/pages/FileManagementPage/FileForm/UserCombobox.vue +66 -0
- package/src/pages/FileManagementPage/FileForm/index.ts +3 -0
- package/src/pages/FileManagementPage/FileList/FileEditButton.vue +410 -0
- package/src/pages/FileManagementPage/FileList/FileList.vue +178 -0
- package/src/pages/FileManagementPage/FileList/index.ts +4 -0
- package/src/pages/FileManagementPage/FileShow/FileShow.vue +23 -0
- package/src/pages/FileManagementPage/FileShow/FileShowData.vue +35 -0
- package/src/pages/FileManagementPage/FileShow/index.ts +3 -0
- package/src/pages/FileManagementPage/FileUpdate/FileUpdate.vue +107 -0
- package/src/pages/FileManagementPage/FileUpdate/index.ts +4 -0
- package/src/pages/FileManagementPage/index.vue +20 -0
- package/src/pages/MediaDocPage/MediaDocCard.vue +35 -0
- package/src/pages/MediaDocPage/MediaDocPage.vue +78 -0
- package/src/pages/UserStoragePage/UserStorage.vue +311 -0
- package/src/pages/UserStoragePage/UserStorageForm/UserStorageForm.vue +172 -0
- package/src/pages/UserStoragePage/UserStorageUpdate/UserStorageUpdate.vue +91 -0
- package/src/pages/UserStoragePage/index.vue +14 -0
- package/src/providers/FileMetricsProvider.ts +47 -0
- package/src/providers/FileProvider.ts +60 -0
- package/src/providers/UploadProvider.ts +32 -0
- package/src/providers/UserStorageProvider.ts +47 -0
- package/src/providers/gql/almacenamientoPorUsuario.graphql +10 -0
- package/src/providers/gql/cantidadArchivosPorUsuario.graphql +10 -0
- package/src/providers/gql/fetchMediaVariables.graphql +6 -0
- package/src/providers/gql/fileCreate.graphql +27 -0
- package/src/providers/gql/fileDelete.graphql +7 -0
- package/src/providers/gql/fileFetch.graphql +29 -0
- package/src/providers/gql/fileFind.graphql +29 -0
- package/src/providers/gql/fileGlobalMetrics.graphql +6 -0
- package/src/providers/gql/filePaginate.graphql +38 -0
- package/src/providers/gql/fileUpdate.graphql +29 -0
- package/src/providers/gql/fileUpload.graphql +29 -0
- package/src/providers/gql/fileUploadAnonymous.graphql +25 -0
- package/src/providers/gql/fileUserMetrics.graphql +9 -0
- package/src/providers/gql/userStorageFetch.graphql +17 -0
- package/src/providers/gql/userStorageFindByUser.graphql +17 -0
- package/src/providers/gql/userStorageUpdate.graphql +31 -0
- package/src/routes/index.ts +32 -0
- package/vite.config.ts +65 -0
- package/vue.config.js +22 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-container>
|
|
3
|
+
<v-row>
|
|
4
|
+
<v-col cols="12" sm="6" md="6">
|
|
5
|
+
<date-time-input
|
|
6
|
+
v-model="expirationDate"
|
|
7
|
+
:label="$t('media.file.expirationDate')"
|
|
8
|
+
prepend-inner-icon="mdi-calendar-clock"
|
|
9
|
+
color="secondary"
|
|
10
|
+
hide-details
|
|
11
|
+
:rules="fileExpirationTimeRules"/>
|
|
12
|
+
</v-col>
|
|
13
|
+
|
|
14
|
+
<v-col cols="12" sm="6" md="6">
|
|
15
|
+
<v-select
|
|
16
|
+
prepend-inner-icon="mdi-eye"
|
|
17
|
+
v-model="isPublic"
|
|
18
|
+
:items="[{title: 'Público', value: true}, {title: 'Privado', value: false}]"
|
|
19
|
+
:label="$t('media.file.visibility')"
|
|
20
|
+
></v-select>
|
|
21
|
+
</v-col>
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
<v-col cols="12" sm="12" md="12" >
|
|
25
|
+
<v-combobox
|
|
26
|
+
prepend-inner-icon="mdi-tag-multiple"
|
|
27
|
+
v-model="tags"
|
|
28
|
+
:label="$t('media.file.tags')"
|
|
29
|
+
multiple
|
|
30
|
+
chips
|
|
31
|
+
color="secondary"
|
|
32
|
+
item-color="secondary"
|
|
33
|
+
></v-combobox>
|
|
34
|
+
</v-col>
|
|
35
|
+
|
|
36
|
+
<v-col cols="12" sm="12" md="12" >
|
|
37
|
+
<v-text-field
|
|
38
|
+
prepend-inner-icon="mdi-text-box"
|
|
39
|
+
name="filename"
|
|
40
|
+
v-model="description"
|
|
41
|
+
:label="$t('media.file.description')"
|
|
42
|
+
:placeholder="$t('media.file.description')"
|
|
43
|
+
color="secondary"
|
|
44
|
+
></v-text-field>
|
|
45
|
+
</v-col>
|
|
46
|
+
</v-row>
|
|
47
|
+
|
|
48
|
+
<v-container class="mb-0 pb-0">
|
|
49
|
+
<input type="file"
|
|
50
|
+
style="display: none"
|
|
51
|
+
ref="fileInput"
|
|
52
|
+
:accept="accept"
|
|
53
|
+
@change="onFilePicked"
|
|
54
|
+
:disabled="disableUploadButton"
|
|
55
|
+
/>
|
|
56
|
+
|
|
57
|
+
<v-menu
|
|
58
|
+
v-model="showErrorMessage"
|
|
59
|
+
:min-width="200"
|
|
60
|
+
:close-on-content-click="false"
|
|
61
|
+
:close-on-click="false"
|
|
62
|
+
offset-x
|
|
63
|
+
>
|
|
64
|
+
<template v-slot:activator="{ props }">
|
|
65
|
+
<v-btn @click="pickFile()"
|
|
66
|
+
fab
|
|
67
|
+
:color="getState.color"
|
|
68
|
+
:loading="loading"
|
|
69
|
+
:size="xLarge ? 'x-large' : undefined"
|
|
70
|
+
v-bind="props"
|
|
71
|
+
>
|
|
72
|
+
<v-avatar v-if="isImage">
|
|
73
|
+
<v-img :src="getSrc" alt="image"/>
|
|
74
|
+
</v-avatar>
|
|
75
|
+
<v-icon v-else-if="isAudio">mdi-headset</v-icon>
|
|
76
|
+
<v-icon v-else-if="isVideo">mdi-videocam</v-icon>
|
|
77
|
+
<v-icon v-else>{{ getState.icon }}</v-icon>
|
|
78
|
+
</v-btn>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<v-card :style="{width: '280px'}" elevation="0">
|
|
82
|
+
<v-card-text class="pb-0 pa-0">
|
|
83
|
+
<v-alert class="mb-0" border="start" type="error" variant="outlined">
|
|
84
|
+
{{ errorMessage }}
|
|
85
|
+
</v-alert>
|
|
86
|
+
</v-card-text>
|
|
87
|
+
<v-card-actions class="justify-center">
|
|
88
|
+
<v-btn text color="primary" @click="resetUpload" class="ml-2">OK</v-btn>
|
|
89
|
+
</v-card-actions>
|
|
90
|
+
</v-card>
|
|
91
|
+
|
|
92
|
+
</v-menu>
|
|
93
|
+
|
|
94
|
+
<p class="mb-0 mt-5">{{(file) == null ? $t('media.file.chooseFile') : file.name}}</p>
|
|
95
|
+
</v-container>
|
|
96
|
+
</v-container>
|
|
97
|
+
</template>
|
|
98
|
+
|
|
99
|
+
<script setup>
|
|
100
|
+
import { ref, computed, onMounted } from 'vue'
|
|
101
|
+
import { useI18n } from 'vue-i18n'
|
|
102
|
+
import uploadProvider from "../../providers/UploadProvider";
|
|
103
|
+
import UserStorageProvider from "../../providers/UserStorageProvider"
|
|
104
|
+
import { DateTimeInput } from '@testdracul/dayjs-frontend';
|
|
105
|
+
import dayjs from 'dayjs'
|
|
106
|
+
|
|
107
|
+
const { t } = useI18n()
|
|
108
|
+
|
|
109
|
+
const props = defineProps({
|
|
110
|
+
autoSubmit: {type: Boolean, default: false},
|
|
111
|
+
accept: {type: String, default: '*'},
|
|
112
|
+
xLarge: {type: Boolean, default: false},
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
const emit = defineEmits(['filePicked', 'fileUploaded'])
|
|
116
|
+
|
|
117
|
+
const INITIAL = 'initial'
|
|
118
|
+
const SELECTED = 'selected'
|
|
119
|
+
const UPLOADED = 'uploaded'
|
|
120
|
+
const ERROR = 'error'
|
|
121
|
+
|
|
122
|
+
const dialog = ref(false)
|
|
123
|
+
const dialogTitle = ref(null)
|
|
124
|
+
const title = 'media.file.creating'
|
|
125
|
+
const errorMessage = ref(null)
|
|
126
|
+
const showErrorMessage = ref(null)
|
|
127
|
+
const inputErrors = ref({})
|
|
128
|
+
const file = ref(null)
|
|
129
|
+
const type = ref(null)
|
|
130
|
+
const uploadedFile = ref(null)
|
|
131
|
+
const state = ref(INITIAL)
|
|
132
|
+
const maxFileSize = ref(0)
|
|
133
|
+
const expirationDate = ref(null)
|
|
134
|
+
const fileExpirationTime = ref(null)
|
|
135
|
+
|
|
136
|
+
const disableUploadButton = ref(false)
|
|
137
|
+
|
|
138
|
+
const loading = ref(false)
|
|
139
|
+
const isPublic = ref(false)
|
|
140
|
+
const description = ref(null)
|
|
141
|
+
const tags = ref([])
|
|
142
|
+
const fileInput = ref(null)
|
|
143
|
+
|
|
144
|
+
const states = {
|
|
145
|
+
initial: { color: 'blue-grey', icon: 'mdi-cloud-upload' },
|
|
146
|
+
selected: { color: 'cyan-darken-3', icon: 'mdi-publish' },
|
|
147
|
+
loading: { color: 'amber-darken-3', icon: '' },
|
|
148
|
+
uploaded: { color: 'green-darken-3', icon: 'mdi-magnify-plus' },
|
|
149
|
+
error: { color: 'red-darken-3', icon: 'mdi-alert' },
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const getState = computed(() => {
|
|
153
|
+
if (loading.value) return states.loading
|
|
154
|
+
return states[state.value]
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
const isImage = computed(() => !!(uploadedFile.value && uploadedFile.value.type === 'image'))
|
|
158
|
+
const isAudio = computed(() => !!(uploadedFile.value && uploadedFile.value.type === 'audio'))
|
|
159
|
+
const isVideo = computed(() => !!(uploadedFile.value && uploadedFile.value.type === 'video'))
|
|
160
|
+
const getSrc = computed(() => (uploadedFile.value && uploadedFile.value.url) ? uploadedFile.value.url : null)
|
|
161
|
+
|
|
162
|
+
const getDifferenceInDays = computed(() => {
|
|
163
|
+
if (expirationDate.value) {
|
|
164
|
+
const today = dayjs();
|
|
165
|
+
const expDate = dayjs(expirationDate.value);
|
|
166
|
+
if (!expDate.isValid()) return null;
|
|
167
|
+
return expDate.diff(today, 'day');
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
const fileExpirationTimeRules = computed(() => [
|
|
173
|
+
() => {
|
|
174
|
+
disableUploadButton.value = true;
|
|
175
|
+
if (getDifferenceInDays.value === null) {
|
|
176
|
+
disableUploadButton.value = false;
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (getDifferenceInDays.value < 0) {
|
|
181
|
+
return t("media.userStorage.fileExpirationTimeOlderThanToday")
|
|
182
|
+
} else if (fileExpirationTime.value && (getDifferenceInDays.value >= fileExpirationTime.value)) {
|
|
183
|
+
return `${t("media.userStorage.fileExpirationLimitExceeded")} ${fileExpirationTime.value} ${t("media.file.days")}`
|
|
184
|
+
}
|
|
185
|
+
disableUploadButton.value = false;
|
|
186
|
+
return true
|
|
187
|
+
}
|
|
188
|
+
])
|
|
189
|
+
|
|
190
|
+
const pickFile = () => {
|
|
191
|
+
if (state.value === INITIAL) {
|
|
192
|
+
fileInput.value.click()
|
|
193
|
+
} else if (state.value === SELECTED) {
|
|
194
|
+
upload()
|
|
195
|
+
} else if (state.value === UPLOADED || state.value === ERROR) {
|
|
196
|
+
dialog.value = true
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const onFilePicked = (e) => {
|
|
201
|
+
file.value = e.target.files[0]
|
|
202
|
+
state.value = SELECTED
|
|
203
|
+
const fileSize = e.target.files[0].size ? e.target.files[0].size / (1024 * 1024) : null;
|
|
204
|
+
emit('filePicked', fileSize);
|
|
205
|
+
if (props.autoSubmit) {
|
|
206
|
+
upload(fileSize)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const findUserStorage = () => {
|
|
211
|
+
return UserStorageProvider.findUserStorageByUser().then((res) => {
|
|
212
|
+
if (res.data.userStorageFindByUser && res.data.userStorageFindByUser.maxFileSize) {
|
|
213
|
+
maxFileSize.value = res.data.userStorageFindByUser.maxFileSize;
|
|
214
|
+
fileExpirationTime.value = res.data.userStorageFindByUser.fileExpirationTime;
|
|
215
|
+
}
|
|
216
|
+
}).catch(err => console.error(err))
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const upload = async (fileSize) => {
|
|
220
|
+
if (file.value && state.value !== UPLOADED && fileSize <= maxFileSize.value) {
|
|
221
|
+
loading.value = true;
|
|
222
|
+
|
|
223
|
+
// Aseguramos que la fecha tenga una hora por defecto si no se seleccionó (ej. fin del día)
|
|
224
|
+
let finalExpiration = expirationDate.value;
|
|
225
|
+
if (finalExpiration) {
|
|
226
|
+
const d = dayjs(finalExpiration);
|
|
227
|
+
if (d.hour() === 0 && d.minute() === 0) {
|
|
228
|
+
finalExpiration = d.hour(23).minute(59).toISOString();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
await uploadProvider.uploadFile(file.value, finalExpiration, isPublic.value, description.value, tags.value).then(result => {
|
|
233
|
+
uploadedFile.value = result.data.fileUpload;
|
|
234
|
+
setState(UPLOADED);
|
|
235
|
+
}).catch((err) => {
|
|
236
|
+
console.error("ERROR", err)
|
|
237
|
+
setState(ERROR);
|
|
238
|
+
setErrorMessage(err.message);
|
|
239
|
+
showErrorMessage.value = true;
|
|
240
|
+
}).finally(() => loading.value = false);
|
|
241
|
+
emit('fileUploaded', uploadedFile.value);
|
|
242
|
+
return uploadedFile.value;
|
|
243
|
+
} else {
|
|
244
|
+
setErrorFileExceeded();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const resetUpload = () => {
|
|
249
|
+
showErrorMessage.value = false;
|
|
250
|
+
setState(INITIAL);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const setErrorFileExceeded = () => {
|
|
254
|
+
setState(ERROR);
|
|
255
|
+
setErrorMessage(`${t("media.file.fileSizeExceeded")} ${maxFileSize.value} Mb`);
|
|
256
|
+
showErrorMessage.value = true;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const setState = (newState) => {
|
|
260
|
+
state.value = newState;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const setErrorMessage = (msg) => {
|
|
264
|
+
errorMessage.value = msg;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
onMounted(() => {
|
|
268
|
+
findUserStorage();
|
|
269
|
+
})
|
|
270
|
+
</script>
|
|
271
|
+
|
|
272
|
+
<style scoped>
|
|
273
|
+
|
|
274
|
+
</style>
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
|
|
4
|
+
<input type="file"
|
|
5
|
+
style="display: none"
|
|
6
|
+
ref="fileInput"
|
|
7
|
+
:accept="accept"
|
|
8
|
+
@change="onFilePicked"
|
|
9
|
+
/>
|
|
10
|
+
|
|
11
|
+
<v-menu
|
|
12
|
+
v-model="showErrorMessage"
|
|
13
|
+
:min-width="200"
|
|
14
|
+
:close-on-content-click="false"
|
|
15
|
+
:close-on-click="false"
|
|
16
|
+
offset-x
|
|
17
|
+
>
|
|
18
|
+
<template v-slot:activator="{ props }">
|
|
19
|
+
<v-btn @click="pickFile()"
|
|
20
|
+
fab
|
|
21
|
+
:color="getState.color"
|
|
22
|
+
:loading="loading"
|
|
23
|
+
:size="xLarge ? 'x-large' : undefined"
|
|
24
|
+
v-bind="props"
|
|
25
|
+
>
|
|
26
|
+
<v-avatar v-if="isImage">
|
|
27
|
+
<v-img :src="getSrc" alt="image"/>
|
|
28
|
+
</v-avatar>
|
|
29
|
+
<v-icon v-else-if="isAudio">mdi-headset</v-icon>
|
|
30
|
+
<v-icon v-else-if="isVideo">mdi-videocam</v-icon>
|
|
31
|
+
<v-icon v-else>{{ getState.icon }}</v-icon>
|
|
32
|
+
</v-btn>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<v-card :style="{width: '280px'}" elevation="0">
|
|
36
|
+
<v-card-text class="pb-0 pa-0">
|
|
37
|
+
<v-alert class="mb-0" border="start" type="error" variant="outlined">
|
|
38
|
+
{{ errorMessage }}
|
|
39
|
+
</v-alert>
|
|
40
|
+
</v-card-text>
|
|
41
|
+
<v-card-actions class="justify-center">
|
|
42
|
+
<v-btn text color="primary" @click="resetUpload" class="ml-2">OK</v-btn>
|
|
43
|
+
</v-card-actions>
|
|
44
|
+
</v-card>
|
|
45
|
+
|
|
46
|
+
</v-menu>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script setup>
|
|
51
|
+
import { ref, computed, onMounted } from 'vue'
|
|
52
|
+
import { useI18n } from 'vue-i18n'
|
|
53
|
+
import uploadProvider from "../../providers/UploadProvider";
|
|
54
|
+
import UserStorageProvider from "../../providers/UserStorageProvider"
|
|
55
|
+
|
|
56
|
+
const { t } = useI18n()
|
|
57
|
+
|
|
58
|
+
const props = defineProps({
|
|
59
|
+
autoSubmit: {type: Boolean, default: false},
|
|
60
|
+
accept: {type: String, default: '*'},
|
|
61
|
+
xLarge: {type: Boolean, default: false},
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const emit = defineEmits(['fileUploaded'])
|
|
65
|
+
|
|
66
|
+
const INITIAL = 'initial'
|
|
67
|
+
const SELECTED = 'selected'
|
|
68
|
+
const UPLOADED = 'uploaded'
|
|
69
|
+
const ERROR = 'error'
|
|
70
|
+
|
|
71
|
+
const dialog = ref(false)
|
|
72
|
+
const dialogTitle = ref(null)
|
|
73
|
+
const title = 'media.file.creating'
|
|
74
|
+
const showErrorMessage = ref(false)
|
|
75
|
+
const errorMessage = ref('')
|
|
76
|
+
const inputErrors = ref({})
|
|
77
|
+
const file = ref(null)
|
|
78
|
+
const type = ref(null)
|
|
79
|
+
const uploadedFile = ref(null)
|
|
80
|
+
const state = ref(INITIAL)
|
|
81
|
+
const maxFileSize = ref(0)
|
|
82
|
+
const loading = ref(false)
|
|
83
|
+
const fileInput = ref(null)
|
|
84
|
+
|
|
85
|
+
const states = {
|
|
86
|
+
initial: {
|
|
87
|
+
color: 'blue-grey',
|
|
88
|
+
icon: 'mdi-cloud-upload'
|
|
89
|
+
},
|
|
90
|
+
selected: {
|
|
91
|
+
color: 'cyan-darken-3',
|
|
92
|
+
icon: 'mdi-publish'
|
|
93
|
+
},
|
|
94
|
+
loading: {
|
|
95
|
+
color: 'amber-darken-3',
|
|
96
|
+
icon: ''
|
|
97
|
+
},
|
|
98
|
+
uploaded: {
|
|
99
|
+
color: 'green-darken-3',
|
|
100
|
+
icon: 'mdi-check'
|
|
101
|
+
},
|
|
102
|
+
error: {
|
|
103
|
+
color: 'red-darken-3',
|
|
104
|
+
icon: 'mdi-alert'
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const getState = computed(() => {
|
|
109
|
+
if (loading.value) return states.loading
|
|
110
|
+
return states[state.value]
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
const isImage = computed(() => {
|
|
114
|
+
return (uploadedFile.value && uploadedFile.value.type === 'image') ? true : false
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const isAudio = computed(() => {
|
|
118
|
+
return (uploadedFile.value && uploadedFile.value.type === 'audio') ? true : false
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
const isVideo = computed(() => {
|
|
122
|
+
return (uploadedFile.value && uploadedFile.value.type === 'video') ? true : false
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const getSrc = computed(() => {
|
|
126
|
+
if (uploadedFile.value && uploadedFile.value.url) {
|
|
127
|
+
return uploadedFile.value.url
|
|
128
|
+
}
|
|
129
|
+
return null
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const pickFile = () => {
|
|
133
|
+
if (state.value === INITIAL) {
|
|
134
|
+
fileInput.value.click()
|
|
135
|
+
} else if (state.value === SELECTED) {
|
|
136
|
+
upload()
|
|
137
|
+
} else if (state.value === UPLOADED || state.value === ERROR) {
|
|
138
|
+
dialog.value = true
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const onFilePicked = (e) => {
|
|
143
|
+
file.value = e.target.files[0]
|
|
144
|
+
state.value = SELECTED
|
|
145
|
+
const fileSize = e.target.files[0].size ? e.target.files[0].size / (1024 * 1024) : null;
|
|
146
|
+
if (props.autoSubmit) {
|
|
147
|
+
upload(fileSize)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const findUserStorage = () => {
|
|
152
|
+
return UserStorageProvider.findUserStorageByUser().then((res) => {
|
|
153
|
+
if (res.data.userStorageFindByUser && res.data.userStorageFindByUser.maxFileSize) {
|
|
154
|
+
maxFileSize.value = res.data.userStorageFindByUser.maxFileSize;
|
|
155
|
+
}
|
|
156
|
+
}).catch(
|
|
157
|
+
err => console.error(err)
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const upload = (fileSize) => {
|
|
162
|
+
if (file.value && state.value != UPLOADED && fileSize <= maxFileSize.value) {
|
|
163
|
+
loading.value = true
|
|
164
|
+
uploadProvider.uploadFile(file.value)
|
|
165
|
+
.then(result => {
|
|
166
|
+
setState(UPLOADED);
|
|
167
|
+
uploadedFile.value = result.data.fileUpload
|
|
168
|
+
emit('fileUploaded', result.data.fileUpload)
|
|
169
|
+
})
|
|
170
|
+
.catch(err => {
|
|
171
|
+
console.log("ERROR", err)
|
|
172
|
+
setState(ERROR);
|
|
173
|
+
setErrorMessage(err.message)
|
|
174
|
+
showErrorMessage.value = true
|
|
175
|
+
})
|
|
176
|
+
.finally(() => loading.value = false)
|
|
177
|
+
} else {
|
|
178
|
+
setErrorFileExceeded()
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const resetUpload = () => {
|
|
183
|
+
showErrorMessage.value = false;
|
|
184
|
+
setState(INITIAL);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const setErrorFileExceeded = () => {
|
|
188
|
+
setState(ERROR);
|
|
189
|
+
setErrorMessage(`${t("media.file.fileSizeExceeded")} ${maxFileSize.value} Mb`);
|
|
190
|
+
showErrorMessage.value = true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const setState = (newState) => {
|
|
194
|
+
state.value = newState;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const setErrorMessage = (msg) => {
|
|
198
|
+
errorMessage.value = msg;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
onMounted(() => {
|
|
202
|
+
findUserStorage();
|
|
203
|
+
})
|
|
204
|
+
</script>
|
|
205
|
+
|
|
206
|
+
<style scoped>
|
|
207
|
+
|
|
208
|
+
</style>
|