[A] vuejs frontend: load , list, display, skip, play/pause, server poll file list
This commit is contained in:
parent
ccb306f325
commit
17add0d254
8 changed files with 12138 additions and 18 deletions
|
|
@ -3,3 +3,4 @@ WEBDAV_USER=user
|
||||||
WEBDAV_PW=pass
|
WEBDAV_PW=pass
|
||||||
WEBFRAME_PATH=/path/to/imgs/
|
WEBFRAME_PATH=/path/to/imgs/
|
||||||
PORT=3000
|
PORT=3000
|
||||||
|
POLL_TIMEOUT=60000
|
||||||
|
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ dist
|
||||||
dist-bkp
|
dist-bkp
|
||||||
.env
|
.env
|
||||||
files/*
|
files/*
|
||||||
|
db.json
|
||||||
|
|
||||||
# https://github.com/github/gitignore/blob/master/Node.gitignore
|
# https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||||
# Logs
|
# Logs
|
||||||
|
|
|
||||||
39
index.js
39
index.js
|
|
@ -8,7 +8,7 @@ const low = require('lowdb');
|
||||||
const FileSync = require('lowdb/adapters/FileSync');
|
const FileSync = require('lowdb/adapters/FileSync');
|
||||||
const adapter = new FileSync('db.json');
|
const adapter = new FileSync('db.json');
|
||||||
const db = low(adapter);
|
const db = low(adapter);
|
||||||
// db.defaults({ files: [], count: 0}).write();
|
db.defaults({ files: [], count: 0}).write();
|
||||||
|
|
||||||
// create webdav-client
|
// create webdav-client
|
||||||
const client = createClient(
|
const client = createClient(
|
||||||
|
|
@ -29,20 +29,25 @@ function dlFile(file, dir = process.env.WEBFRAME_PATH) {
|
||||||
return client.createReadStream(dir+'/'+file).pipe(fs.createWriteStream('./files/'+file));
|
return client.createReadStream(dir+'/'+file).pipe(fs.createWriteStream('./files/'+file));
|
||||||
}
|
}
|
||||||
|
|
||||||
client.exists(process.env.WEBFRAME_PATH).then(async data => {
|
function loadImages() {
|
||||||
if (data) {
|
client.exists(process.env.WEBFRAME_PATH).then(async data => {
|
||||||
const list = await listDir(process.env.WEBFRAME_PATH);
|
if (data) {
|
||||||
list.forEach(file => {
|
const list = await listDir(process.env.WEBFRAME_PATH);
|
||||||
// if (!fs.existsSync('./files/'+file.basename)) {
|
list.forEach(file => {
|
||||||
const inDb = db.get('files').find({ basename: file.basename }).value() !== undefined ? true : false;
|
const inDb = db.get('files').find({ basename: file.basename }).value() !== undefined ? true : false;
|
||||||
if (!inDb) {
|
if (!inDb) {
|
||||||
dlFile(file.basename);
|
console.log('Downloaded new File:', file.basename);
|
||||||
db.get('files').push(file).write();
|
dlFile(file.basename);
|
||||||
db.update('count', n => n + 1).write();
|
db.get('files').push(file).write();
|
||||||
}
|
db.update('count', n => n + 1).write();
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
setTimeout(() => loadImages(), process.env.POLL_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadImages();
|
||||||
|
|
||||||
// webserver
|
// webserver
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
|
@ -50,8 +55,8 @@ const app = express();
|
||||||
|
|
||||||
app.use('/files', express.static(path.join(__dirname, 'files')));
|
app.use('/files', express.static(path.join(__dirname, 'files')));
|
||||||
app.get('/api/files', (req, res) => {
|
app.get('/api/files', (req, res) => {
|
||||||
res.json(db.get('files').value());
|
res.json({resource: db.get('files').value()});
|
||||||
});
|
});
|
||||||
app.use('*', express.static(path.join(__dirname, 'public')));
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
app.listen(process.env.PORT, () => console.log(`Example app listening at http://localhost:${process.env.PORT}`));
|
app.listen(process.env.PORT, () => console.log(`Example app listening at http://localhost:${process.env.PORT}`));
|
||||||
|
|
||||||
|
|
|
||||||
57
public/app.js
Normal file
57
public/app.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data: {
|
||||||
|
files: [],
|
||||||
|
index: 0,
|
||||||
|
timeout: null,
|
||||||
|
carouselTimeout: 10000,
|
||||||
|
carouselActive: true
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
next: function () {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
setTimeout(() => this.carousel(), this.carouselTimeout*2);
|
||||||
|
if (this.index + 1 < this.files.length) {
|
||||||
|
this.index++;
|
||||||
|
} else {
|
||||||
|
this.index = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prev: function () {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
setTimeout(() => this.carousel(), this.carouselTimeout*2);
|
||||||
|
if (this.index - 1 >= 0) {
|
||||||
|
this.index--;
|
||||||
|
} else {
|
||||||
|
this.index = this.files.length - 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
carousel: function (time = this.carouselTimeout) {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.next();
|
||||||
|
this.carousel();
|
||||||
|
}, time);
|
||||||
|
},
|
||||||
|
loadData: function () {
|
||||||
|
fetch('api/files').then(response => response.json()).then(
|
||||||
|
data => {
|
||||||
|
this.files = data.resource;
|
||||||
|
this.carousel();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
toggleCarousel: function () {
|
||||||
|
if (this.carouselActive) {
|
||||||
|
this.carouselActive = false;
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
console.log(this.timeout)
|
||||||
|
} else {
|
||||||
|
this.carouselActive = true;
|
||||||
|
this.carousel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
})
|
||||||
51
public/index.css
Normal file
51
public/index.css
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#app, #app div {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
z-index: 0;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app video {
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .floatBtn {
|
||||||
|
display: block;
|
||||||
|
width: 40px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 100%;
|
||||||
|
background-color: rgba(0,0,0,.3);
|
||||||
|
color: white;
|
||||||
|
z-index: 10;
|
||||||
|
position: absolute;
|
||||||
|
top: 50vh;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .floatBtn.left {
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .floatBtn.right {
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .floatBtn.bottom {
|
||||||
|
left: 49%;
|
||||||
|
top: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app .empty {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 48vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1 +1,35 @@
|
||||||
index
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>WebFrame</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" type="text/css" href="index.css">
|
||||||
|
<script src="vue.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<div v-if="files && files.length > 0">
|
||||||
|
<div class="floatBtn left" v-on:click="prev()">
|
||||||
|
-
|
||||||
|
</div>
|
||||||
|
<div class="floatBtn right" v-on:click="next()">
|
||||||
|
+
|
||||||
|
</div>
|
||||||
|
<div class="floatBtn bottom" v-on:click="toggleCarousel()">
|
||||||
|
<span v-if="!carouselActive">Play</span>
|
||||||
|
<span v-if="carouselActive">Pause</span>
|
||||||
|
</div>
|
||||||
|
<img v-if="files[index].mime.includes('image')" v-bind:src="'/files/'+files[index].basename" alt="">
|
||||||
|
<video v-if="files[index].mime.includes('video')" autoplay muted loop>
|
||||||
|
<source v-bind:src="'/files/'+files[index].basename" v-bind:type="files[index].mime">
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
<div v-else class="empty">
|
||||||
|
No images
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="app.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
11965
public/vue.js
Normal file
11965
public/vue.js
Normal file
File diff suppressed because it is too large
Load diff
6
public/vue.min.js
vendored
Normal file
6
public/vue.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue