Convert upload page to vue

This commit is contained in:
2025-05-03 20:37:15 +02:00
parent 3571f93e41
commit 457bab2c18
6 changed files with 134 additions and 19 deletions

View File

@@ -1,6 +1,8 @@
# Spot Project # Spot Project
[Spot](https://www.findmespot.com) & GPX integration [Spot](https://www.findmespot.com) & GPX integration
## Dependencies ## Dependencies
* npm 18+ * npm 18+
* composer * composer
* php-mbstring * php-mbstring
@@ -11,13 +13,17 @@
* ffprobe & ffmpeg * ffprobe & ffmpeg
* STARTTLS Email Server (use Gmail if none available) * STARTTLS Email Server (use Gmail if none available)
* Optional: Geo Caching Server (WMTS Caching Service) * Optional: Geo Caching Server (WMTS Caching Service)
## PHP Configuration ## PHP Configuration
* max_execution_time = 300 * max_execution_time = 300
* memory_limit = 500M * memory_limit = 500M
* post_max_size = 4G * post_max_size = 4G
* upload_max_filesize = 4G * upload_max_filesize = 4G
* max_file_uploads = 50 * max_file_uploads = 50
## Getting started ## Getting started
1. Clone Git onto web server 1. Clone Git onto web server
2. composer install 2. composer install
3. npm install webpack 3. npm install webpack
@@ -27,7 +33,9 @@
7. Copy settings-sample.php to settings.php and populate 7. Copy settings-sample.php to settings.php and populate
8. Go to #admin and create a new project, feed & maps 8. Go to #admin and create a new project, feed & maps
9. Add a GPX file named <project_codename>.gpx to /geo/ 9. Add a GPX file named <project_codename>.gpx to /geo/
## To Do List ## To Do List
* Add mail frequency slider * Add mail frequency slider
* Use WMTS servers directly when not using Geo Caching Server * Use WMTS servers directly when not using Geo Caching Server
* Allow HEIF picture format * Allow HEIF picture format

View File

@@ -1,21 +1,27 @@
<script> <script>
import Project from './components/project.vue'; import Project from './components/project.vue';
import Admin from './components/admin.vue'; import Admin from './components/admin.vue';
import Upload from './components/upload.vue';
const aoRoutes = { const aoRoutes = {
'project': Project, 'project': Project,
'admin': Admin 'admin': Admin,
'upload': Upload
}; };
export default { export default {
data() { data() {
return { return {
hash: {} hash: {},
consts: this.spot.consts,
user: this.spot.vars('user')
}; };
}, },
provide() { provide() {
return { return {
projects: this.spot.vars('projects') projects: this.spot.vars('projects'),
consts: this.consts,
user: this.user
}; };
}, },
inject: ['spot'], inject: ['spot'],
@@ -25,12 +31,15 @@ export default {
return aoRoutes[this.hash.page]; return aoRoutes[this.hash.page];
} }
}, },
created() {
//User
this.user.timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || this.consts.default_timezone;
},
mounted() { mounted() {
window.addEventListener('hashchange', () => {this.onHashChange();}); window.addEventListener('hashchange', () => {this.onHashChange();});
var oEvent = new Event('hashchange'); var oEvent = new Event('hashchange');
window.dispatchEvent(oEvent); window.dispatchEvent(oEvent);
} },
,
methods: { methods: {
_hash(hash, bReboot) { _hash(hash, bReboot) {
bReboot = bReboot || false; bReboot = bReboot || false;

View File

@@ -38,7 +38,6 @@ export default {
posts: [], posts: [],
nlFeedbacks: [], nlFeedbacks: [],
nlLoading: false, nlLoading: false,
user: {name:'', email:''},
baseMaps: {}, baseMaps: {},
baseMap: null, baseMap: null,
messages: null, messages: null,
@@ -86,11 +85,10 @@ export default {
}, },
provide() { provide() {
return { return {
user: this.user,
project: this.project project: this.project
}; };
}, },
inject: ['spot', 'projects'], inject: ['spot', 'projects', 'user'],
mounted() { mounted() {
this.spot.addPage('project', { this.spot.addPage('project', {
onResize: () => { onResize: () => {
@@ -112,7 +110,6 @@ export default {
this.initProject(); this.initProject();
if(bFirstLoad) this.initLightbox(); if(bFirstLoad) this.initLightbox();
this.initFeed(); this.initFeed();
if(bFirstLoad) this.initSettings();
this.initMap(); this.initMap();
}, },
initProject() { initProject() {
@@ -154,9 +151,6 @@ export default {
//Scroll to post //Scroll to post
if(this.$parent.hash.items.length == 3) this.findPost({type: this.$parent.hash.items[1], id: this.$parent.hash.items[2]}); if(this.$parent.hash.items.length == 3) this.findPost({type: this.$parent.hash.items[1], id: this.$parent.hash.items[2]});
}, },
initSettings() {
this.user = this.spot.vars('user');
},
async initMap() { async initMap() {
//Get Map Info //Get Map Info
const aoMarkers = await this.spot.get2('markers', {id_project: this.project.id}); const aoMarkers = await this.spot.get2('markers', {id_project: this.project.id});

77
src/components/upload.vue Normal file
View File

@@ -0,0 +1,77 @@
<script>
import SpotButton from './spotButton.vue';
import "blueimp-file-upload/js/vendor/jquery.ui.widget.js";
import "blueimp-file-upload/js/jquery.iframe-transport.js";
import "blueimp-file-upload/js/jquery.fileupload.js";
export default {
name: 'upload',
components: { SpotButton },
inject: ['spot', 'projects', 'consts', 'user'],
data() {
return {
project: this.projects[this.spot.vars('default_project_codename')],
files: [],
logs: [],
progress: 0
};
},
mounted() {
this.spot.addPage('upload', {});
if(this.project.editable) {
$('#fileupload')
.fileupload({
dataType: 'json',
formData: {t: this.user.timezone},
acceptFileTypes: /(\.|\/)(gif|jpe?g|png|mov)$/i,
done: (e, asData) => {
$.each(asData.result.files, (iKey, oFile) => {
let bError = ('error' in oFile);
//Feedback
this.logs.push(bError?oFile.error:(this.spot.lang('upload_success', [oFile.name])));
//Comments
oFile.content = '';
if(!bError) this.files.push(oFile);
});
},
progressall: (e, data) => {
this.progress = parseInt(data.loaded / data.total * 100, 10);
}
});
}
else this.logs = [this.spot.lang('upload_mode_archived', [this.project.name])];
},
methods: {
addComment(oFile) {
this.spot.get2('add_comment', {id: oFile.id, content: oFile.content})
.then((asData) => {this.logs.push(this.spot.lang('media_comment_update', asData.filename));})
.catch((sMsgId) => {this.logs.push(this.spot.lang(sMsgId));});
}
}
}
</script>
<template>
<div id="upload">
<a name="back" class="button" href="#project"><i class="fa fa-back push"></i>{{ spot.lang('nav_back') }}</a>
<h1>{{ spot.lang('upload_title') }}</h1>
<h2>{{ this.project.name }}</h2>
<input v-if="project.editable" id="fileupload" type="file" name="files[]" :data-url="this.spot.getActionLink('upload')" multiple>
<div class="progress" v-if="progress > 0">
<div class="bar" :style="{width:progress+'%'}"></div>
</div>
<div class="comment" v-for="file in files">
<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" />
<SpotButton :classes="'save'" :icon="'save'" :text="spot.lang('save')" @click="addComment(file)" />
</div>
</div>
<div class="logs" v-if="logs.length > 0">
<p class="log" v-for="log in logs">{{ log }}.</p>
</div>
</div>
</template>

View File

@@ -79,6 +79,9 @@ $fa-css-prefix: fa;
.#{$fa-css-prefix}-config:before { content: fa-content($fa-var-cogs); } .#{$fa-css-prefix}-config:before { content: fa-content($fa-var-cogs); }
.#{$fa-css-prefix}-upload:before { content: fa-content($fa-var-cloud-upload); } .#{$fa-css-prefix}-upload:before { content: fa-content($fa-var-cloud-upload); }
/* Upload */
.#{$fa-css-prefix}-save:before { content: fa-content($fa-var-floppy-disk); }
/* Feed */ /* Feed */
.#{$fa-css-prefix}-post:before { content: fa-content($fa-var-comment); } .#{$fa-css-prefix}-post:before { content: fa-content($fa-var-comment); }
.#{$fa-css-prefix}-media:before { content: fa-content($fa-var-photo-video); } .#{$fa-css-prefix}-media:before { content: fa-content($fa-var-photo-video); }

View File

@@ -1,9 +1,20 @@
#upload { #upload {
padding: 1em; padding: 1em;
.bar { input[type="file"] {
height: 18px; border: 1px solid #333;
background: green; border-radius: 3px;
}
.progress {
margin: 1rem 0;
border: 1px solid #333;
border-radius: 3px;
.bar {
height: 18px;
background: green;
}
} }
.comment { .comment {
@@ -13,7 +24,8 @@
width: 30%; width: 30%;
max-width: 100px; max-width: 100px;
} }
form {
.form {
display: inline-block; display: inline-block;
width: calc(70% - 1em); width: calc(70% - 1em);
min-width: calc(100% - 100px - 1em); min-width: calc(100% - 100px - 1em);
@@ -25,6 +37,7 @@
box-sizing: border-box; box-sizing: border-box;
padding: 0.5em; padding: 0.5em;
border: 1px solid #333; border: 1px solid #333;
border-radius: 3px;
} }
.save { .save {
@@ -33,4 +46,15 @@
} }
} }
} }
.logs {
border: 1px solid #333;
border-radius: 3px;
margin-top: 1rem;
padding: 1rem;
p.log {
margin: 0;
}
}
} }