159 lines
5.1 KiB
Vue
159 lines
5.1 KiB
Vue
<script>
|
|
import { markRaw } from 'vue';
|
|
import Uppy from '@uppy/core';
|
|
import XHRUpload from '@uppy/xhr-upload';
|
|
import '@uppy/core/css/style.min.css';
|
|
|
|
import AppIcon from '@components/AppIcon';
|
|
import AppButton from '@components/AppButton';
|
|
|
|
export default {
|
|
name: 'upload',
|
|
components: { AppButton, AppIcon },
|
|
inject: ['api', 'lang', 'projects', 'consts', 'user', 'getPrevAnchor'],
|
|
data() {
|
|
return {
|
|
project: this.projects.getDefaultProject(),
|
|
files: [],
|
|
logs: [],
|
|
progress: 0,
|
|
uppy: null
|
|
};
|
|
},
|
|
mounted() {
|
|
if(!this.project.editable) {
|
|
this.addLog('upload.mode_archived', [this.project.name]);
|
|
return;
|
|
}
|
|
|
|
this.initUploader();
|
|
},
|
|
beforeUnmount() {
|
|
if(this.uppy) {
|
|
this.uppy.destroy();
|
|
this.uppy = null;
|
|
}
|
|
},
|
|
methods: {
|
|
addLog(sLangId = 'upload.error', asLangParams = []) {
|
|
this.logs.push({lang_id: sLangId, lang_params: asLangParams});
|
|
},
|
|
initUploader() {
|
|
const endpoint = `${this.consts.process_page}?a=upload`;
|
|
|
|
this.uppy = markRaw(new Uppy({
|
|
autoProceed: true,
|
|
restrictions: {
|
|
allowedFileTypes: ['.gif', '.jpg', '.jpeg', '.png', '.mov', '.mp4']
|
|
}
|
|
}));
|
|
|
|
this.uppy.setMeta({t: this.user.timezone});
|
|
|
|
this.uppy.use(XHRUpload, {
|
|
endpoint,
|
|
fieldName: 'files[]',
|
|
formData: true,
|
|
headers: {'X-CSRF-Token': this.consts.csrf_token},
|
|
allowedMetaFields: ['t', 'name', 'type'],
|
|
getResponseData(xhr) {
|
|
return JSON.parse(xhr.responseText || '{}');
|
|
}
|
|
});
|
|
|
|
this.uppy.on('progress', (progress) => {
|
|
this.progress = progress;
|
|
});
|
|
|
|
this.uppy.on('upload-success', (file, response) => {
|
|
const uploadedFiles = response?.body?.files || [];
|
|
uploadedFiles.forEach((uploadedFile) => {
|
|
const hasError = Object.prototype.hasOwnProperty.call(uploadedFile, 'error');
|
|
if(hasError) this.addLog(uploadedFile.desc_lang_id, uploadedFile.desc_lang_params);
|
|
else this.addLog('upload.success', [uploadedFile.original_name || uploadedFile.name]);
|
|
if(!hasError) this.files.push({...uploadedFile, content: ''});
|
|
});
|
|
});
|
|
|
|
this.uppy.on('upload-error', (file, error, response) => {
|
|
this.addLog(response?.body?.desc_lang_id || 'upload.error', response?.body?.desc_lang_params || []);
|
|
});
|
|
|
|
this.uppy.on('complete', () => {
|
|
this.progress = 0;
|
|
});
|
|
},
|
|
onFileChange(event) {
|
|
const files = Array.from(event.target.files || []);
|
|
if(files.length > 0 && this.uppy) this.uppy.addFiles(files.map((file) => ({source: 'local', name: file.name, type: file.type, data: file})));
|
|
event.target.value = '';
|
|
},
|
|
addComment(oFile) {
|
|
this.api.post('add_comment', {
|
|
id: oFile.id,
|
|
content: oFile.content
|
|
})
|
|
.then((asData) => {this.addLog('media.comment_update', [asData.filename]);})
|
|
.catch((oError) => {this.addLog(oError.desc_lang_id, oError.desc_lang_params);});
|
|
},
|
|
addPosition() {
|
|
if(navigator.geolocation) {
|
|
this.addLog('upload.position.determining');
|
|
navigator.geolocation.getCurrentPosition(
|
|
(position) => {
|
|
this.addLog('upload.position.sending');
|
|
this.api.post('add_position', {
|
|
'latitude': position.coords.latitude,
|
|
'longitude': position.coords.longitude,
|
|
'timestamp': Math.round(position.timestamp / 1000)
|
|
})
|
|
.then(() => {this.addLog('upload.position.success');})
|
|
.catch((oError) => {this.addLog(oError.desc_lang_id, oError.desc_lang_params);});
|
|
},
|
|
(error) => {
|
|
const asErrorLangIds = {
|
|
1: 'upload.position.permission_denied',
|
|
2: 'upload.position.unavailable',
|
|
3: 'upload.position.timeout'
|
|
};
|
|
this.addLog(asErrorLangIds[error.code] || 'upload.position.error');
|
|
}
|
|
);
|
|
}
|
|
else this.addLog('upload.position.unsupported');
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<template>
|
|
<div id="upload">
|
|
<div class="section header">
|
|
<a name="back" class="button" :href="getPrevAnchor()"><AppIcon :icon="'back'" :text="lang.get('action.back')" /></a>
|
|
<h1>{{ this.project.name }}</h1>
|
|
</div>
|
|
<div class="section" v-if="project.editable">
|
|
<h2>{{ lang.get('upload.media.title') }}</h2>
|
|
<input id="fileupload" type="file" name="files[]" multiple accept=".gif,.jpg,.jpeg,.png,.mov,.mp4" @change="onFileChange" />
|
|
</div>
|
|
<div class="section progress" v-if="progress > 0">
|
|
<div class="total"></div>
|
|
<div class="bar" :style="{width:progress+'%'}"></div>
|
|
</div>
|
|
<div class="section comment" v-for="file in files" :key="file.id">
|
|
<img class="thumb" :src="file.thumbnail" />
|
|
<div class="form">
|
|
<input class="content" name="content" type="text" v-model="file.content" />
|
|
<input class="id" name="id" type="hidden" :value="file.id" />
|
|
<AppButton :classes="'save'" :icon="'save'" :text="lang.get('action.save')" @click="addComment(file)" />
|
|
</div>
|
|
</div>
|
|
<div class="section location" v-if="project.editable">
|
|
<h2>{{ lang.get('upload.position.title') }}</h2>
|
|
<AppButton :icon="'marker'" :text="lang.get('upload.position.new')" @click="addPosition()" />
|
|
</div>
|
|
<div class="section logs" v-if="logs.length > 0">
|
|
<p class="log" v-for="(log, index) in logs" :key="index">{{ lang.get(log.lang_id, log.lang_params) }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|