[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
|
||||
WEBFRAME_PATH=/path/to/imgs/
|
||||
PORT=3000
|
||||
POLL_TIMEOUT=60000
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ dist
|
|||
dist-bkp
|
||||
.env
|
||||
files/*
|
||||
db.json
|
||||
|
||||
# https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
|
|
|
|||
39
index.js
39
index.js
|
|
@ -8,7 +8,7 @@ const low = require('lowdb');
|
|||
const FileSync = require('lowdb/adapters/FileSync');
|
||||
const adapter = new FileSync('db.json');
|
||||
const db = low(adapter);
|
||||
// db.defaults({ files: [], count: 0}).write();
|
||||
db.defaults({ files: [], count: 0}).write();
|
||||
|
||||
// create webdav-client
|
||||
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));
|
||||
}
|
||||
|
||||
client.exists(process.env.WEBFRAME_PATH).then(async data => {
|
||||
if (data) {
|
||||
const list = await listDir(process.env.WEBFRAME_PATH);
|
||||
list.forEach(file => {
|
||||
// if (!fs.existsSync('./files/'+file.basename)) {
|
||||
const inDb = db.get('files').find({ basename: file.basename }).value() !== undefined ? true : false;
|
||||
if (!inDb) {
|
||||
dlFile(file.basename);
|
||||
db.get('files').push(file).write();
|
||||
db.update('count', n => n + 1).write();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
function loadImages() {
|
||||
client.exists(process.env.WEBFRAME_PATH).then(async data => {
|
||||
if (data) {
|
||||
const list = await listDir(process.env.WEBFRAME_PATH);
|
||||
list.forEach(file => {
|
||||
const inDb = db.get('files').find({ basename: file.basename }).value() !== undefined ? true : false;
|
||||
if (!inDb) {
|
||||
console.log('Downloaded new File:', file.basename);
|
||||
dlFile(file.basename);
|
||||
db.get('files').push(file).write();
|
||||
db.update('count', n => n + 1).write();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
setTimeout(() => loadImages(), process.env.POLL_TIMEOUT);
|
||||
}
|
||||
|
||||
loadImages();
|
||||
|
||||
// webserver
|
||||
const express = require('express');
|
||||
|
|
@ -50,8 +55,8 @@ const app = express();
|
|||
|
||||
app.use('/files', express.static(path.join(__dirname, 'files')));
|
||||
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}`));
|
||||
|
||||
|
|
|
|||
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