From 313dfe99cf8f763b36f333c5072e2430a6b7941f Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Tue, 3 Mar 2020 17:57:28 +0100 Subject: Use custom public folder listing --- frontend/404.html | 2 +- frontend/js/public.js | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ frontend/public.html | 89 +++++++++++++++++++++++++++++++ 3 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 frontend/js/public.js create mode 100644 frontend/public.html (limited to 'frontend') diff --git a/frontend/404.html b/frontend/404.html index c660424..15da5c2 100644 --- a/frontend/404.html +++ b/frontend/404.html @@ -9,7 +9,7 @@
-

File not found

+

File or directory not found

diff --git a/frontend/js/public.js b/frontend/js/public.js new file mode 100644 index 0000000..c295a05 --- /dev/null +++ b/frontend/js/public.js @@ -0,0 +1,144 @@ +(function () { + 'use strict'; + + /* global superagent */ + /* global Vue */ + /* global $ */ + /* global filesize */ + + function sanitize(filePath) { + filePath = '/' + filePath; + return filePath.replace(/\/+/g, '/'); + } + + function encode(filePath) { + return filePath.split('/').map(encodeURIComponent).join('/'); + } + + function decode(filePath) { + return filePath.split('/').map(decodeURIComponent).join('/'); + } + + var mimeTypes = { + images: [ '.png', '.jpg', '.jpeg', '.tiff', '.gif' ], + text: [ '.txt', '.md' ], + pdf: [ '.pdf' ], + html: [ '.html', '.htm', '.php' ], + video: [ '.mp4', '.mpg', '.mpeg', '.ogg', '.mkv', '.avi', '.mov' ] + }; + + function getPreviewUrl(entry, basePath) { + var path = '/_admin/img/'; + + if (entry.isDirectory) return path + 'directory.png'; + if (mimeTypes.images.some(function (e) { return entry.filePath.endsWith(e); })) return sanitize(basePath + '/' + entry.filePath); + if (mimeTypes.text.some(function (e) { return entry.filePath.endsWith(e); })) return path +'text.png'; + if (mimeTypes.pdf.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'pdf.png'; + if (mimeTypes.html.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'html.png'; + if (mimeTypes.video.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'video.png'; + + return path + 'unknown.png'; + } + + // simple extension detection, does not work with double extension like .tar.gz + function getExtension(entry) { + if (entry.isFile) return entry.filePath.slice(entry.filePath.lastIndexOf('.') + 1); + return ''; + } + + function loadDirectory() { + app.busy = true; + + var filePath = sanitize(window.location.pathname); + + app.path = filePath; + + superagent.get('/api/files/' + encode(filePath)).query({ access_token: localStorage.accessToken }).end(function (error, result) { + app.busy = false; + + if (result && result.statusCode === 401) return logout(); + if (error) return console.error(error); + + result.body.entries.sort(function (a, b) { return a.isDirectory && b.isFile ? -1 : 1; }); + app.entries = result.body.entries.map(function (entry) { + entry.previewUrl = getPreviewUrl(entry, filePath); + entry.extension = getExtension(entry); + entry.rename = false; + entry.filePathNew = entry.filePath; + return entry; + }); + app.path = filePath; + app.pathParts = decode(filePath).split('/').filter(function (e) { return !!e; }).map(function (e, i, a) { + return { + name: e, + link: '#' + sanitize('/' + a.slice(0, i).join('/') + '/' + e) + }; + }); + }); + } + + function open(row, column, event) { + var fullPath = encode(sanitize(app.path + '/' + row.filePath)); + + if (row.isDirectory) return window.location.href = fullPath; + + app.activeEntry = row; + app.activeEntry.fullPath = fullPath; + app.previewDrawerVisible = true + + // need to wait for DOM element to exist + setTimeout(function () { + $('iframe').on('load', function (e) { + if (!e.target.contentWindow.document.body) return; + + e.target.contentWindow.document.body.style.display = 'flex' + e.target.contentWindow.document.body.style.justifyContent = 'center' + }); + }, 0); + } + + var app = new Vue({ + el: '#app', + data: { + ready: false, + busy: false, + path: '', + previewDrawerVisible: false, + activeEntry: {}, + entries: [] + }, + methods: { + onDownload: function (entry) { + if (entry.isDirectory) return; + window.location.href = encode('/api/files/' + sanitize(this.path + '/' + entry.filePath)) + '?access_token=' + localStorage.accessToken; + }, + prettyDate: function (row, column, cellValue, index) { + var date = new Date(cellValue), + diff = (((new Date()).getTime() - date.getTime()) / 1000), + day_diff = Math.floor(diff / 86400); + + if (isNaN(day_diff) || day_diff < 0) + return; + + return day_diff === 0 && ( + diff < 60 && 'just now' || + diff < 120 && '1 minute ago' || + diff < 3600 && Math.floor( diff / 60 ) + ' minutes ago' || + diff < 7200 && '1 hour ago' || + diff < 86400 && Math.floor( diff / 3600 ) + ' hours ago') || + day_diff === 1 && 'Yesterday' || + day_diff < 7 && day_diff + ' days ago' || + day_diff < 31 && Math.ceil( day_diff / 7 ) + ' weeks ago' || + day_diff < 365 && Math.round( day_diff / 30 ) + ' months ago' || + Math.round( day_diff / 365 ) + ' years ago'; + }, + prettyFileSize: function (row, column, cellValue, index) { + return filesize(cellValue); + }, + loadDirectory: loadDirectory, + open: open, + } + }); + + loadDirectory(); +})(); \ No newline at end of file diff --git a/frontend/public.html b/frontend/public.html new file mode 100644 index 0000000..2ddf543 --- /dev/null +++ b/frontend/public.html @@ -0,0 +1,89 @@ + + + Surfer + + + + + + + + + + + + + + + + + + +
+ + + + +
+

{{ path }}

+
+ +
+
+ + +
+

+
+ +
+
+ + + + + + + + + + + +
+
+ +
+
+ Folder is empty +
+
+ + +
+ +
+ Download + + Open + +
+
+
+ +
+
+ +
+ + + + + -- cgit v1.2.3