You are logged in
- - - - - diff --git a/src/main.js b/src/main.js index 330267559..db0af7961 100644 --- a/src/main.js +++ b/src/main.js @@ -10,8 +10,8 @@ import PrimeVue from 'primevue/config'; import { createRouter, createWebHashHistory } from 'vue-router'; import App from './App.vue'; -import Login from './components/Login.vue'; -import Home from './components/Home.vue'; +import Login from './views/Login.vue'; +import Home from './views/Home.vue'; const routes = [ { path: '/home', component: Home }, diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 000000000..03713ed27 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,196 @@ + +import { filesize } from 'filesize'; + +function prettyDate(value) { + var date = new Date(value), + 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 min ago' || + diff < 3600 && Math.floor( diff / 60 ) + ' min 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'; +} + +function prettyLongDate(value) { + if (!value) return 'unkown'; + + var date = new Date(value); + return `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`; +} + +function prettyFileSize(value) { + if (typeof value !== 'number') return 'unkown'; + + return filesize(value); +} + +function sanitize(path) { + path = '/' + path; + return path.replace(/\/+/g, '/'); +} + +function encode(path) { + return path.split('/').map(encodeURIComponent).join('/'); +} + +function decode(path) { + return path.split('/').map(decodeURIComponent).join('/'); +} + +// TODO create share links instead of using access token +function getDirectLink(entry) { + if (entry.share) { + let link = window.location.origin + '/api/v1/shares/' + entry.share.id + '?type=raw&path=' + encodeURIComponent(entry.filePath); + return link; + } else { + return window.location.origin + '/api/v1/files?type=raw&path=' + encodeURIComponent(entry.filePath); + } +} + +// TODO the url might actually return a 412 in which case we have to keep reloading +function getPreviewUrl(entry) { + if (!entry.previewUrl) return ''; + return entry.previewUrl; +} + +function getShareLink(shareId) { + return window.location.origin + '/api/v1/shares/' + shareId + '?type=raw'; +} + +function download(entries, name) { + if (!entries.length) return; + + if (entries.length === 1) { + if (entries[0].share) window.location.href = '/api/v1/shares/' + entries[0].share.id + '?type=download&path=' + encodeURIComponent(entries[0].filePath); + else window.location.href = '/api/v1/files?type=download&path=' + encodeURIComponent(entries[0].filePath); + + return; + } + + const params = new URLSearchParams(); + + // be a bit smart about the archive name and folder tree + const folderPath = entries[0].filePath.slice(0, -entries[0].fileName.length); + const archiveName = name || folderPath.slice(folderPath.slice(0, -1).lastIndexOf('/')+1).slice(0, -1); + params.append('name', archiveName); + params.append('skipPath', folderPath); + + params.append('entries', JSON.stringify(entries.map(function (entry) { + return { + filePath: entry.filePath, + shareId: entry.share ? entry.share.id : undefined + }; + }))); + + window.location.href = '/api/v1/download?' + params.toString(); +} + +function getFileTypeGroup(entry) { + return entry.mimeType.split('/')[0]; +} + +// simple extension detection, does not work with double extension like .tar.gz +function getExtension(entry) { + if (entry.isFile) return entry.fileName.slice(entry.fileName.lastIndexOf('.') + 1); + return ''; +} + +function copyToClipboard(value) { + var elem = document.createElement('input'); + elem.value = value; + document.body.append(elem); + elem.select(); + document.execCommand('copy'); + elem.remove(); +} + +function clearSelection() { + if(document.selection && document.selection.empty) { + document.selection.empty(); + } else if(window.getSelection) { + var sel = window.getSelection(); + sel.removeAllRanges(); + } +} + +function urlSearchQuery() { + return decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {}); +} + +// those paths contain the internal type and path reference eg. shares/:shareId/folder/filename or files/folder/filename +function parseResourcePath(resourcePath) { + var result = { + type: '', + path: '', + shareId: '', + apiPath: '', + resourcePath: '' + }; + + if (resourcePath.indexOf('files/') === 0) { + result.type = 'files'; + result.path = resourcePath.slice('files'.length) || '/'; + result.apiPath = '/api/v1/files'; + result.resourcePath = result.type + result.path; + } else if (resourcePath.indexOf('shares/') === 0) { + result.type = 'shares'; + result.shareId = resourcePath.split('/')[1]; + result.path = resourcePath.slice((result.type + '/' + result.shareId).length) || '/'; + result.apiPath = '/api/v1/shares/' + result.shareId; + // without shareId we show the root (share listing) + result.resourcePath = result.type + '/' + (result.shareId ? (result.shareId + result.path) : ''); + } else { + console.error('Unknown resource path', resourcePath); + } + + return result; +} + +function getEntryIdentifier(entry) { + return (entry.share ? (entry.share.id + '/') : '') + entry.filePath; +} + +function entryListSort(list, prop, desc) { + var tmp = list.sort(function (a, b) { + var av = a[prop]; + var bv = b[prop]; + + if (typeof av === 'string') return (av.toUpperCase() < bv.toUpperCase()) ? -1 : 1; + else return (av < bv) ? -1 : 1; + }); + + if (desc) return tmp; + return tmp.reverse(); +} + +export { + getDirectLink, + getPreviewUrl, + getShareLink, + getFileTypeGroup, + prettyDate, + prettyLongDate, + prettyFileSize, + sanitize, + encode, + decode, + download, + getExtension, + copyToClipboard, + clearSelection, + urlSearchQuery, + parseResourcePath, + getEntryIdentifier, + entryListSort +}; diff --git a/src/views/Home.vue b/src/views/Home.vue new file mode 100644 index 000000000..97d8ed2f5 --- /dev/null +++ b/src/views/Home.vue @@ -0,0 +1,42 @@ + +
@@ -91,6 +29,69 @@ setTimeout(function () { document.getElementById('usernameInput').focus(); }, 0)