Browse Source

List and thumb view on uploads

Pitu 7 years ago
parent
commit
3f4b879144
8 changed files with 159 additions and 54 deletions
  1. BIN
      .DS_Store
  2. 4 0
      config.sample.js
  3. 40 2
      controllers/uploadController.js
  4. 2 1
      lolisafe.js
  5. 2 0
      package.json
  6. 3 0
      public/css/style.css
  7. 104 49
      public/js/panel.js
  8. 4 2
      public/js/upload.js

BIN
.DS_Store


+ 4 - 0
config.sample.js

@@ -39,6 +39,10 @@ module.exports = {
 
 		// The length of the random generated name for the uploaded files
 		fileLength: 32,
+
+		// NOTE: Thumbnails are only for the admin panel and they require you
+		// to install a separate binary called graphicsmagick (http://www.graphicsmagick.org)
+		generateThumbnails: false
 	},
 
 	// Folder where to store logs

+ 40 - 2
controllers/uploadController.js

@@ -5,6 +5,7 @@ const randomstring = require('randomstring')
 const db = require('knex')(config.database)
 const crypto = require('crypto')
 const fs = require('fs')
+const gm = require('gm')
 
 let uploadsController = {}
 
@@ -152,7 +153,10 @@ uploadsController.delete = function(req, res){
 				return res.json({ success: true })
 			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 		}).catch((e) => {
-			return res.json({ success: false, description: e.toString() })
+			console.log(e.toString())
+			db.table('files').where('id', id).del().then(() =>{
+				return res.json({ success: true })
+			}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 		})
 
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
@@ -212,14 +216,48 @@ uploadsController.list = function(req, res){
 						if(file.albumid === album.id)
 							file.album = album.name
 
+				if(config.uploads.generateThumbnails === true){
+
+					let extensions = ['.jpg', '.jpeg', '.bmp', '.gif', '.png']
+					for(let ext of extensions){
+						if(path.extname(file.name) === ext){
+
+							file.thumb = basedomain + '/thumbs/' + file.name.slice(0, -4) + '.png'
+
+							let thumbname = path.join(__dirname, '..', 'uploads', 'thumbs') + '/' + file.name.slice(0, -4) + '.png'
+							fs.access(thumbname, function(err) {
+								if (err && err.code === 'ENOENT') {
+									// File doesnt exist
+
+									let size = {
+										width: 200, 
+										height: 200
+									}
+
+									gm('./' + config.uploads.folder + '/' + file.name)
+										.resize(size.width, size.height + '>')
+										.gravity('Center')
+										.extent(size.width, size.height)
+										.background('transparent')
+										.write(thumbname, function (error) {
+											if (error) console.log('Error - ', error)
+										})
+								}
+							})
+						}
+					}
+
+				}
+				
+
 			}
 
 			return res.json({
 				success: true,
 				files
 			})
-		})
 
+		}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 	}).catch(function(error) { console.log(error); res.json({success: false, description: 'error'}) })
 }
 

+ 2 - 1
lolisafe.js

@@ -8,8 +8,9 @@ const safe = express()
 
 require('./database/db.js')(db, config)
 
-fs.existsSync('./' + config.uploads.folder) || fs.mkdirSync('./' + config.uploads.folder)
 fs.existsSync('./' + config.logsFolder) || fs.mkdirSync('./' + config.logsFolder)
+fs.existsSync('./' + config.uploads.folder) || fs.mkdirSync('./' + config.uploads.folder)
+fs.existsSync('./' + config.uploads.folder + '/thumbs') || fs.mkdirSync('./' + config.uploads.folder + '/thumbs')
 
 safe.use(bodyParser.urlencoded({ extended: true }))
 safe.use(bodyParser.json())

+ 2 - 0
package.json

@@ -17,8 +17,10 @@
   "dependencies": {
     "body-parser": "^1.16.0",
     "express": "^4.14.0",
+    "gm": "^1.23.0",
     "knex": "^0.12.6",
     "multer": "^1.2.1",
+    "node-thumbnail": "^0.7.0",
     "randomstring": "^1.1.5",
     "sqlite3": "^3.1.8"
   }

+ 3 - 0
public/css/style.css

@@ -89,3 +89,6 @@ section#auth input, section#auth a {
 }
 
 section#dashboard .table { font-size: 12px }
+section#dashboard div#table div.column { display:flex; width: 200px; height: 200px; margin: 9px; background: #f9f9f9; overflow: hidden; align-items: center; }
+section#dashboard div#table div.column a { width: 100%; }
+section#dashboard div#table div.column a img { width:200px; }

+ 104 - 49
public/js/panel.js

@@ -2,6 +2,7 @@ let panel = {}
 
 panel.page;
 panel.token = localStorage.admintoken;
+panel.filesView = localStorage.filesView;
 
 panel.preparePage = function(){
 	if(!panel.token){
@@ -14,8 +15,10 @@ panel.preparePage = function(){
 	panel.verifyToken(panel.token, true);
 }
 
-panel.verifyToken = function(token, reloadOnError = false){
-	
+panel.verifyToken = function(token, reloadOnError){
+	if(reloadOnError === undefined)
+		reloadOnError = false;
+
 	axios.post('/api/tokens/verify', {
 		type: 'admin',
 		token: token
@@ -100,63 +103,109 @@ panel.getUploads = function(album = undefined, page = undefined){
 
 		panel.page.innerHTML = '';
 		var container = document.createElement('div');
-		container.innerHTML = `
-			<div class='columns'>
-				<div class="column">
-					<nav class="pagination is-centered">
-				  		<a class="pagination-previous" onclick="panel.getUploads(${album}, ${prevPage} )">Previous</a>
-				  		<a class="pagination-next" onclick="panel.getUploads(${album}, ${nextPage} )">Next page</a>
-					</nav>
-				</div>
+		var pagination = `<nav class="pagination is-centered">
+					  		<a class="pagination-previous" onclick="panel.getUploads(${album}, ${prevPage} )">Previous</a>
+					  		<a class="pagination-next" onclick="panel.getUploads(${album}, ${nextPage} )">Next page</a>
+						</nav>`;
+		var listType = `
+		<div class="columns">
+			<div class="column">
+				<a class="button is-small is-outlined is-danger" title="List view" onclick="panel.setFilesView('list', ${album}, ${page})">
+					<span class="icon is-small">
+						<i class="fa fa-list-ul"></i>
+					</span>
+				</a>
+				<a class="button is-small is-outlined is-danger" title="List view" onclick="panel.setFilesView('thumbs', ${album}, ${page})">
+					<span class="icon is-small">
+						<i class="fa fa-th-large"></i>
+					</span>
+				</a>
 			</div>
+		</div>`
+
+		if(panel.filesView === 'thumbs'){
+
+
+			container.innerHTML = `
+				
+				${pagination}
+				<hr>
+				${listType}
+				<div class="columns is-multiline is-mobile" id="table">
 
-			<table class="table is-striped is-narrow">
-				<thead>
-					<tr>
-						  <th>File</th>
-						  <th>Album</th>
-						  <th>Date</th>
-						  <th></th>
-					</tr>
-				</thead>
-				<tbody id="table">
-				</tbody>
-			</table>
-
-			<div class='columns'>
-				<div class="column">
-					<nav class="pagination is-centered">
-				  		<a class="pagination-previous" onclick="panel.getUploads(${album}, ${prevPage} )">Previous</a>
-				  		<a class="pagination-next" onclick="panel.getUploads(${album}, ${nextPage} )">Next page</a>
-					</nav>
 				</div>
-			</div>
+				${pagination}
+
 			`;
-		panel.page.appendChild(container);
 
-		var table = document.getElementById('table');
 
-		for(var item of response.data.files){
+			panel.page.appendChild(container);
+			var table = document.getElementById('table');
 
-			var tr = document.createElement('tr');
-			tr.innerHTML = `
-				<tr>
-					<th><a href="${item.file}" target="_blank">${item.file}</a></th>
-					<th>${item.album}</th>
-					<td>${item.date}</td>
-					<td>
-						<a class="button is-small is-danger is-outlined" title="Delete album" onclick="panel.deleteFile(${item.id})">
-							<span class="icon is-small">
-								<i class="fa fa-trash-o"></i>
-							</span>
-						</a>
-					</td>
-				</tr>
-				`;
+			for(var item of response.data.files){
+
+				var div = document.createElement('div');
+				div.className = "column is-2";
+				if(item.thumb !== undefined)
+					div.innerHTML = `<a href="${item.file}" target="_blank"><img src="${item.thumb}"/></a>`;
+				else
+					div.innerHTML = `<a href="${item.file}" target="_blank"><h1 class="title">.${item.file.split('.').pop()}</h1></a>`;
+				table.appendChild(div);
+
+			}
+
+		}else{
+
+			container.innerHTML = `
+				
+				${pagination}
+				<hr>
+				${listType}
+				<table class="table is-striped is-narrow is-left">
+					<thead>
+						<tr>
+							  <th>File</th>
+							  <th>Album</th>
+							  <th>Date</th>
+							  <th></th>
+						</tr>
+					</thead>
+					<tbody id="table">
+					</tbody>
+				</table>
+				<hr>
+				${pagination}
+
+			`;
+
+			panel.page.appendChild(container);
+			var table = document.getElementById('table');
+
+			for(var item of response.data.files){
+
+				var tr = document.createElement('tr');
+				tr.innerHTML = `
+					<tr>
+						<th><a href="${item.file}" target="_blank">${item.file}</a></th>
+						<th>${item.album}</th>
+						<td>${item.date}</td>
+						<td>
+							<a class="button is-small is-danger is-outlined" title="Delete album" onclick="panel.deleteFile(${item.id})">
+								<span class="icon is-small">
+									<i class="fa fa-trash-o"></i>
+								</span>
+							</a>
+						</td>
+					</tr>
+					`;
+
+				table.appendChild(tr);
+			}
 
-			table.appendChild(tr);
 		}
 
+
+
 	})
 	.catch(function (error) {
 		return swal("An error ocurred", 'There was an error with the request, please check the console for more information.', "error");
@@ -165,6 +214,12 @@ panel.getUploads = function(album = undefined, page = undefined){
 
 }
 
+panel.setFilesView = function(view, album, page){
+	localStorage.filesView = view;
+	panel.filesView = view;
+	panel.getUploads(album, page);
+}
+
 panel.deleteFile = function(id){
 	swal({
 		title: "Are you sure?",

+ 4 - 2
public/js/upload.js

@@ -31,8 +31,10 @@ upload.preparePage = function(){
 	upload.verifyToken(upload.token, true);
 }
 
-upload.verifyToken = function(token, reloadOnError = false){
-
+upload.verifyToken = function(token, reloadOnError){
+	if(reloadOnError === undefined)
+		reloadOnError = false;
+	
 	axios.post('/api/tokens/verify', {
 		type: 'client',
 		token: token