/* global swal, axios, ClipboardJS, LazyLoad */ // keys for localStorage const LS_KEYS = { token: 'token', viewType: { uploads: 'UPLOADS_VIEW_TYPE' }, selected: { uploads: 'SELECTED_UPLOADS', users: 'SELECTED_USERS' } } const page = { // #page dom: null, // user token token: localStorage[LS_KEYS.token], // from api/tokens/verify username: null, permissions: null, currentView: null, views: { // config of uploads view uploads: { type: localStorage[LS_KEYS.viewType.uploads], album: null, // album's id pageNum: null, // page num all: null // listing all uploads or just the user's }, // config of users view users: { pageNum: null } }, // id of selected items (shared across pages and will be synced with localStorage) selected: { uploads: [], users: [] }, checkboxes: { uploads: [], users: [] }, lastSelected: { upload: null, user: null }, // select album dom for dialogs/modals selectAlbumContainer: null, // cache for dialogs/modals cache: { uploads: {}, albums: {}, users: {} }, clipboardJS: null, lazyLoad: null, // byte units for getPrettyBytes() byteUnits: ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] } page.preparePage = function () { if (!page.token) { window.location = 'auth' return } page.verifyToken(page.token, true) } page.verifyToken = function (token, reloadOnError) { axios.post('api/tokens/verify', { token }).then(function (response) { if (response.data.success === false) { return swal({ title: 'An error occurred!', text: response.data.description, icon: 'error' }).then(function () { if (!reloadOnError) { return } localStorage.removeItem(LS_KEYS.token) location.location = 'auth' }) } axios.defaults.headers.common.token = token localStorage[LS_KEYS.token] = token page.token = token page.username = response.data.username page.permissions = response.data.permissions page.prepareDashboard() }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.prepareDashboard = function () { page.dom = document.getElementById('page') page.dom.addEventListener('click', page.domClick, true) document.getElementById('auth').style.display = 'none' document.getElementById('dashboard').style.display = 'block' if (page.permissions.moderator) { const itemManageUploads = document.getElementById('itemManageUploads') itemManageUploads.removeAttribute('disabled') itemManageUploads.addEventListener('click', function () { page.setActiveMenu(this) page.getUploads({ all: true }) }) } if (page.permissions.admin) { const itemManageUsers = document.getElementById('itemManageUsers') itemManageUsers.removeAttribute('disabled') itemManageUsers.addEventListener('click', function () { page.setActiveMenu(this) page.getUsers() }) } document.getElementById('itemUploads').addEventListener('click', function () { page.setActiveMenu(this) page.getUploads({ all: false }) }) document.getElementById('itemDeleteByNames').addEventListener('click', function () { page.setActiveMenu(this) page.deleteByNames() }) document.getElementById('itemManageGallery').addEventListener('click', function () { page.setActiveMenu(this) page.getAlbums() }) document.getElementById('itemFileLength').addEventListener('click', function () { page.setActiveMenu(this) page.changeFileLength() }) document.getElementById('itemTokens').addEventListener('click', function () { page.setActiveMenu(this) page.changeToken() }) document.getElementById('itemPassword').addEventListener('click', function () { page.setActiveMenu(this) page.changePassword() }) const logoutBtn = document.getElementById('itemLogout') logoutBtn.addEventListener('click', function () { page.logout() }) logoutBtn.innerHTML = `Logout ( ${page.username} )` page.getAlbumsSidebar() if (typeof page.prepareShareX === 'function') { page.prepareShareX() } } page.logout = function () { localStorage.removeItem(LS_KEYS.token) location.reload('.') } page.getItemID = function (element) { // This expects the item's parent to have the item's ID let parent = element.parentNode // If the element is part of a set of controls, use the container's parent instead if (element.parentNode.classList.contains('controls')) { parent = parent.parentNode } return parseInt(parent.dataset.id) } page.domClick = function (event) { let element = event.target if (!element) { return } // If the clicked element is an icon, delegate event to its A parent; hacky if (element.tagName === 'I' && element.parentNode.tagName === 'SPAN') { element = element.parentNode } if (element.tagName === 'SPAN' && element.parentNode.tagName === 'A') { element = element.parentNode } // Skip elements that have no action data if (!element.dataset || !element.dataset.action) { return } event.stopPropagation() // maybe necessary const id = page.getItemID(element) const action = element.dataset.action // Handle pagination actions if (['page-prev', 'page-next'].includes(action)) { const views = {} let func = null if (page.currentView === 'uploads') { views.album = page.views.uploads.album views.all = page.views.uploads.all func = page.getUploads } else if (page.currentView === 'users') { func = page.getUsers } switch (action) { case 'page-prev': views.pageNum = page.views[page.currentView].pageNum - 1 if (views.pageNum < 0) { return swal('An error occurred!', 'This is already the first page.', 'error') } return func(views, element) case 'page-next': views.pageNum = page.views[page.currentView].pageNum + 1 return func(views, element) } } switch (action) { case 'view-list': return page.setUploadsView('list', element) case 'view-thumbs': return page.setUploadsView('thumbs', element) case 'clear-selection': return page.clearSelection() case 'add-selected-files-to-album': return page.addSelectedFilesToAlbum() case 'bulk-delete': return page.deleteSelectedFiles() case 'select': return page.select(element, event) case 'add-to-album': return page.addSingleFileToAlbum(id) case 'delete-file': return page.deleteFile(id) case 'select-all': return page.selectAll(element) case 'display-thumbnail': return page.displayThumbnail(id) case 'delete-file-by-names': return page.deleteFileByNames() case 'submit-album': return page.submitAlbum(element) case 'edit-album': return page.editAlbum(id) case 'delete-album': return page.deleteAlbum(id) case 'get-new-token': return page.getNewToken(element) case 'edit-user': return page.editUser(id) } } page.isLoading = function (element, state) { if (!element) { return } if (state) { return element.classList.add('is-loading') } element.classList.remove('is-loading') } page.getUploads = function ({ album, pageNum, all } = {}, element) { if (element) { page.isLoading(element, true) } if (pageNum === undefined) { pageNum = 0 } let url = `api/uploads/${pageNum}` if (album !== undefined) { url = `api/album/${album}/${pageNum}` } if (all && !page.permissions.moderator) { return swal('An error occurred!', 'You can not do this!', 'error') } axios.get(url, { headers: { all: all ? '1' : '0' } }).then(function (response) { if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } if (pageNum && (response.data.files.length === 0)) { // Only remove loading class here, since beyond this the entire page will be replaced anyways if (element) { page.isLoading(element, false) } return swal('An error occurred!', 'There are no more uploads.', 'error') } page.currentView = 'uploads' page.cache.uploads = {} const pagination = ` ` const controls = `
${all ? '' : ` `} Bulk delete
` let allSelected = true if (page.views.uploads.type === 'thumbs') { page.dom.innerHTML = ` ${pagination}
${controls}
${pagination} ` const table = document.getElementById('table') for (let i = 0; i < response.data.files.length; i++) { const upload = response.data.files[i] const selected = page.selected.uploads.includes(upload.id) if (!selected && allSelected) { allSelected = false } // Prettify upload.prettyBytes = page.getPrettyBytes(parseInt(upload.size)) upload.prettyDate = page.getPrettyDate(new Date(upload.timestamp * 1000)) let displayAlbumOrUser = upload.album if (all) { displayAlbumOrUser = upload.username || '' } const div = document.createElement('div') div.className = 'image-container column is-narrow' div.dataset.id = upload.id if (upload.thumb !== undefined) { div.innerHTML = `${upload.name}` } else { div.innerHTML = `

${upload.extname || 'N/A'}

` } div.innerHTML += `

${upload.name}

${displayAlbumOrUser ? `${displayAlbumOrUser} – ` : ''}${upload.prettyBytes}

` table.appendChild(div) // page.checkboxes.uploads = Array.from(table.getElementsByClassName('checkbox')) page.checkboxes.uploads = Array.from(table.querySelectorAll('.checkbox[data-action="select"]')) page.lazyLoad.update() } } else { let albumOrUser = 'Album' if (all) { albumOrUser = 'User' } page.dom.innerHTML = ` ${pagination}
${controls}
File ${albumOrUser} Size Date

${pagination} ` const table = document.getElementById('table') for (let i = 0; i < response.data.files.length; i++) { const upload = response.data.files[i] const selected = page.selected.uploads.includes(upload.id) if (!selected && allSelected) { allSelected = false } page.cache.uploads[upload.id] = { name: upload.name, thumb: upload.thumb } // Prettify upload.prettyBytes = page.getPrettyBytes(parseInt(upload.size)) upload.prettyDate = page.getPrettyDate(new Date(upload.timestamp * 1000)) let displayAlbumOrUser = upload.album if (all) { displayAlbumOrUser = upload.username || '' } const tr = document.createElement('tr') tr.dataset.id = upload.id tr.innerHTML = ` ${upload.name} ${displayAlbumOrUser} ${upload.prettyBytes} ${upload.prettyDate} ${all ? '' : ` `} ` table.appendChild(tr) // page.checkboxes.uploads = Array.from(table.getElementsByClassName('checkbox')) page.checkboxes.uploads = Array.from(table.querySelectorAll('.checkbox[data-action="select"]')) } } if (allSelected && response.data.files.length) { const selectAll = document.getElementById('selectAll') if (selectAll) { selectAll.checked = true } } page.views.uploads.album = album page.views.uploads.pageNum = response.data.files.length ? pageNum : 0 page.views.uploads.all = all }).catch(function (error) { if (element) { page.isLoading(element, false) } console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.setUploadsView = function (view, element) { localStorage[LS_KEYS.viewType.uploads] = view page.views.uploads.type = view page.getUploads(page.views.uploads, element) } page.displayThumbnail = function (id) { const file = page.cache.uploads[id] if (!file.thumb) { return } return swal({ text: file.name, content: { element: 'img', attributes: { src: file.thumb } }, button: true }) } page.selectAll = function (element) { const currentView = page.currentView const checkboxes = page.checkboxes[currentView] const selected = page.selected[currentView] for (let i = 0; i < checkboxes.length; i++) { const id = page.getItemID(checkboxes[i]) if (isNaN(id)) { continue } if (checkboxes[i].checked !== element.checked) { checkboxes[i].checked = element.checked if (checkboxes[i].checked) { selected.push(id) } else { selected.splice(selected.indexOf(id), 1) } } } if (selected.length) { localStorage[LS_KEYS.selected[currentView]] = JSON.stringify(selected) } else { localStorage.removeItem(LS_KEYS.selected[currentView]) } page.selected[currentView] = selected element.title = element.checked ? 'Unselect all uploads' : 'Select all uploads' } page.selectInBetween = function (element, lastElement) { if (!element || !lastElement) { return } if (element === lastElement) { return } const currentView = page.currentView const checkboxes = page.checkboxes[currentView] if (!checkboxes || !checkboxes.length) { return } const thisIndex = checkboxes.indexOf(element) const lastIndex = checkboxes.indexOf(lastElement) const distance = thisIndex - lastIndex if (distance >= -1 && distance <= 1) { return } for (let i = 0; i < checkboxes.length; i++) { if ((thisIndex > lastIndex && i > lastIndex && i < thisIndex) || (thisIndex < lastIndex && i > thisIndex && i < lastIndex)) { checkboxes[i].checked = true page.selected[currentView].push(page.getItemID(checkboxes[i])) } } localStorage[LS_KEYS.selected.uploads] = JSON.stringify(page.selected[currentView]) page.checkboxes[currentView] = checkboxes } page.select = function (element, event) { const currentView = page.currentView const lastSelected = page.lastSelected[currentView] if (event.shiftKey && lastSelected) { page.selectInBetween(element, lastSelected) } else { page.lastSelected[currentView] = element } const id = page.getItemID(element) if (isNaN(id)) { return } const selected = page.selected[currentView] if (!selected.includes(id) && element.checked) { selected.push(id) } else if (selected.includes(id) && !element.checked) { selected.splice(selected.indexOf(id), 1) } if (selected.length) { localStorage[LS_KEYS.selected[currentView]] = JSON.stringify(selected) } else { localStorage.removeItem(LS_KEYS.selected[currentView]) } page.selected[currentView] = selected } page.clearSelection = function () { const currentView = page.currentView const selected = page.selected[currentView] const count = selected.length if (!count) { return swal('An error occurred!', `You have not selected any ${currentView}.`, 'error') } const suffix = count === 1 ? currentView.substring(0, currentView.length - 1) : currentView return swal({ title: 'Are you sure?', text: `You are going to unselect ${count} ${suffix}.`, buttons: true }).then(function (proceed) { if (!proceed) { return } const checkboxes = page.checkboxes[currentView] for (let i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkboxes[i].checked = false } } localStorage.removeItem(LS_KEYS.selected[currentView]) page.selected[currentView] = [] const selectAll = document.getElementById('selectAll') if (selectAll) { selectAll.checked = false } return swal('Cleared selection!', `Unselected ${count} ${suffix}.`, 'success') }) } page.deleteFile = function (id) { // TODO: Share function with bulk delete, just like 'add selected uploads to album' and 'add single file to album' swal({ title: 'Are you sure?', text: 'You won\'t be able to recover the file!', icon: 'warning', dangerMode: true, buttons: { cancel: true, confirm: { text: 'Yes, delete it!', closeModal: false } } }).then(function (proceed) { if (!proceed) { return } axios.post('api/upload/delete', { id }).then(function (response) { if (!response) { return } if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Deleted!', 'The file has been deleted.', 'success') page.getUploads(page.views.uploads) }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } page.deleteSelectedFiles = function () { const count = page.selected.uploads.length if (!count) { return swal('An error occurred!', 'You have not selected any uploads.', 'error') } const suffix = `file${count === 1 ? '' : 's'}` swal({ title: 'Are you sure?', text: `You won't be able to recover ${count} ${suffix}!`, icon: 'warning', dangerMode: true, buttons: { cancel: true, confirm: { text: `Yes, nuke the ${suffix}!`, closeModal: false } } }).then(function (proceed) { if (!proceed) { return } axios.post('api/upload/bulkdelete', { field: 'id', values: page.selected.uploads }).then(function (bulkdelete) { if (!bulkdelete) { return } if (bulkdelete.data.success === false) { if (bulkdelete.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', bulkdelete.data.description, 'error') } } let deleted = count if (bulkdelete.data.failed && bulkdelete.data.failed.length) { deleted -= bulkdelete.data.failed.length page.selected.uploads = page.selected.uploads.filter(function (id) { return bulkdelete.data.failed.includes(id) }) } else { page.selected.uploads = [] } localStorage[LS_KEYS.selected.uploads] = JSON.stringify(page.selected.uploads) swal('Deleted!', `${deleted} file${deleted === 1 ? ' has' : 's have'} been deleted.`, 'success') return page.getUploads(page.views.uploads) }).catch(function (error) { console.log(error) swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } page.deleteByNames = function () { page.dom.innerHTML = `

Delete by names

Separate each entry with a new line.

Bulk delete
` } page.deleteFileByNames = function () { const names = document.getElementById('names').value .split(/\r?\n/) .filter(function (n) { return n.trim().length }) const count = names.length if (!count) { return swal('An error occurred!', 'You have not entered any file names.', 'error') } const suffix = `file${count === 1 ? '' : 's'}` swal({ title: 'Are you sure?', text: `You won't be able to recover ${count} ${suffix}!`, icon: 'warning', dangerMode: true, buttons: { cancel: true, confirm: { text: `Yes, nuke the ${suffix}!`, closeModal: false } } }).then(function (proceed) { if (!proceed) { return } axios.post('api/upload/bulkdelete', { field: 'name', values: names }).then(function (bulkdelete) { if (!bulkdelete) { return } if (bulkdelete.data.success === false) { if (bulkdelete.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', bulkdelete.data.description, 'error') } } let deleted = count if (bulkdelete.data.failed && bulkdelete.data.failed.length) { deleted -= bulkdelete.data.failed.length } document.getElementById('names').value = bulkdelete.data.failed.join('\n') swal('Deleted!', `${deleted} file${deleted === 1 ? ' has' : 's have'} been deleted.`, 'success') }).catch(function (error) { console.log(error) swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } page.addSelectedFilesToAlbum = function () { const count = page.selected.uploads.length if (!count) { return swal('An error occurred!', 'You have not selected any uploads.', 'error') } page.addFilesToAlbum(page.selected.uploads, function (failed) { if (!failed) { return } if (failed.length) { page.selected.uploads = page.selected.uploads.filter(function (id) { return failed.includes(id) }) } else { page.selected.uploads = [] } localStorage[LS_KEYS.selected.uploads] = JSON.stringify(page.selected.uploads) page.getUploads(page.views.uploads) }) } page.addSingleFileToAlbum = function (id) { page.addFilesToAlbum([id], function (failed) { if (!failed) { return } page.getUploads(page.views.uploads) }) } page.addFilesToAlbum = function (ids, callback) { const count = ids.length const content = document.createElement('div') content.innerHTML = `

You are about to add ${count} file${count === 1 ? '' : 's'} to an album.

` swal({ title: 'Add to album', icon: 'warning', content, buttons: { cancel: true, confirm: { text: 'OK', closeModal: false } } }).then(function (choose) { if (!choose) { return } const albumid = parseInt(document.getElementById('swalAlbum').value) if (isNaN(albumid)) { return swal('An error occurred!', 'You did not choose an album.', 'error') } axios.post('api/albums/addfiles', { ids, albumid }).then(function (add) { if (!add) { return } if (add.data.success === false) { if (add.data.description === 'No token provided') { page.verifyToken(page.token) } else { swal('An error occurred!', add.data.description, 'error') } return } let added = ids.length if (add.data.failed && add.data.failed.length) { added -= add.data.failed.length } const suffix = `file${ids.length === 1 ? '' : 's'}` if (!added) { return swal('An error occurred!', `Could not add the ${suffix} to the album.`, 'error') } swal('Woohoo!', `Successfully ${albumid < 0 ? 'removed' : 'added'} ${added} ${suffix} ${albumid < 0 ? 'from' : 'to'} the album.`, 'success') return callback(add.data.failed) }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) // Get albums list then update content of swal axios.get('api/albums').then(function (list) { if (list.data.success === false) { if (list.data.description === 'No token provided') { page.verifyToken(page.token) } else { swal('An error occurred!', list.data.description, 'error') } return } const select = document.getElementById('swalAlbum') // If the prompt was replaced, the container would be missing if (!select) { return } select.innerHTML += list.data.albums .map(function (album) { return `` }) .join('\n') select.getElementsByTagName('option')[1].innerHTML = 'Choose an album' select.removeAttribute('disabled') }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.getAlbums = function () { axios.get('api/albums').then(function (response) { if (!response) { return } if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } page.cache.albums = {} page.dom.innerHTML = `

Create new album

Create

List of albums

ID Name Files Created at Public link
` const homeDomain = response.data.homeDomain const table = document.getElementById('table') for (let i = 0; i < response.data.albums.length; i++) { const album = response.data.albums[i] const albumUrl = `${homeDomain}/a/${album.identifier}` // Prettify album.prettyDate = page.getPrettyDate(new Date(album.timestamp * 1000)) page.cache.albums[album.id] = { name: album.name, download: album.download, public: album.public } const tr = document.createElement('tr') tr.innerHTML = ` ${album.id} ${album.name} ${album.files} ${album.prettyDate} ${albumUrl} ` table.appendChild(tr) } }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.editAlbum = function (id) { const album = page.cache.albums[id] if (!album) { return } const div = document.createElement('div') div.innerHTML = `
` swal({ title: 'Edit album', icon: 'info', content: div, buttons: { cancel: true, confirm: { closeModal: false } } }).then(function (value) { if (!value) { return } axios.post('api/albums/edit', { id, name: document.getElementById('swalName').value, download: document.getElementById('swalDownload').checked, public: document.getElementById('swalPublic').checked, requestLink: document.getElementById('swalRequestLink').checked }).then(function (response) { if (!response) { return } if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } if (response.data.identifier) { swal('Success!', `Your album's new identifier is: ${response.data.identifier}.`, 'success') } else if (response.data.name !== album.name) { swal('Success!', `Your album was renamed to: ${response.data.name}.`, 'success') } else { swal('Success!', 'Your album was edited!', 'success') } page.getAlbumsSidebar() page.getAlbums() }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } page.deleteAlbum = function (id) { swal({ title: 'Are you sure?', text: 'This won\'t delete your uploads, only the album!', icon: 'warning', dangerMode: true, buttons: { cancel: true, confirm: { text: 'Yes, delete it!', closeModal: false }, purge: { text: 'Umm, delete the uploads too please?', value: 'purge', className: 'swal-button--danger', closeModal: false } } }).then(function (proceed) { if (!proceed) { return } axios.post('api/albums/delete', { id, purge: proceed === 'purge' }).then(function (response) { if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Deleted!', 'Your album has been deleted.', 'success') page.getAlbumsSidebar() page.getAlbums() }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } page.submitAlbum = function (element) { page.isLoading(element, true) axios.post('api/albums', { name: document.getElementById('albumName').value }).then(function (response) { if (!response) { return } page.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Woohoo!', 'Album was created successfully', 'success') page.getAlbumsSidebar() page.getAlbums() }).catch(function (error) { console.log(error) page.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.getAlbumsSidebar = function () { axios.get('api/albums/sidebar').then(function (response) { if (!response) { return } if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } const albumsContainer = document.getElementById('albumsContainer') albumsContainer.innerHTML = '' if (response.data.albums === undefined) { return } for (let i = 0; i < response.data.albums.length; i++) { const album = response.data.albums[i] const li = document.createElement('li') const a = document.createElement('a') a.id = album.id a.innerHTML = album.name a.addEventListener('click', function () { page.getAlbum(this) }) li.appendChild(a) albumsContainer.appendChild(li) } }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.getAlbum = function (album) { page.setActiveMenu(album) page.getUploads({ album: album.id }) } page.changeFileLength = function () { axios.get('api/filelength/config').then(function (response) { if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } // Shorter vars const { max, min } = response.data.config const [ chg, def ] = [ response.data.config.userChangeable, response.data.config.default ] const len = response.data.fileLength page.dom.innerHTML = `

File name length

Default file name length is ${def} characters. ${(chg ? `Range allowed for user is ${min} to ${max} characters.` : 'Changing file name length is disabled at the moment.')}

` document.getElementById('setFileLength').addEventListener('click', function () { page.setFileLength(document.getElementById('fileLength').value, this) }) }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.setFileLength = function (fileLength, element) { page.isLoading(element, true) axios.post('api/filelength/change', { fileLength }).then(function (response) { page.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal({ title: 'Woohoo!', text: 'Your file length was successfully changed.', icon: 'success' }).then(function () { page.changeFileLength() }) }).catch(function (error) { console.log(error) page.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.changeToken = function () { axios.get('api/tokens').then(function (response) { if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } page.dom.innerHTML = `

Manage your token

` }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.getNewToken = function (element) { page.isLoading(element, true) axios.post('api/tokens/change').then(function (response) { page.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal({ title: 'Woohoo!', text: 'Your token was successfully changed.', icon: 'success' }).then(function () { axios.defaults.headers.common.token = response.data.token localStorage[LS_KEYS.token] = response.data.token page.token = response.data.token page.changeToken() }) }).catch(function (error) { console.log(error) page.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.changePassword = function () { page.dom.innerHTML = `

Change your password

` document.getElementById('sendChangePassword').addEventListener('click', function () { if (document.getElementById('password').value === document.getElementById('passwordConfirm').value) { page.sendNewPassword(document.getElementById('password').value, this) } else { swal({ title: 'Password mismatch!', text: 'Your passwords do not match, please try again.', icon: 'error' }) } }) } page.sendNewPassword = function (pass, element) { page.isLoading(element, true) axios.post('api/password/change', { password: pass }).then(function (response) { page.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal({ title: 'Woohoo!', text: 'Your password was successfully changed.', icon: 'success' }).then(function () { page.changePassword() }) }).catch(function (error) { console.log(error) page.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.setActiveMenu = function (activeItem) { const menu = document.getElementById('menu') const items = menu.getElementsByTagName('a') for (let i = 0; i < items.length; i++) { items[i].classList.remove('is-active') } activeItem.classList.add('is-active') } page.getPrettyDate = date => { return date.getFullYear() + '-' + (date.getMonth() < 9 ? '0' : '') + // month's index starts from zero (date.getMonth() + 1) + '-' + (date.getDate() < 10 ? '0' : '') + date.getDate() + ' ' + (date.getHours() < 10 ? '0' : '') + date.getHours() + ':' + (date.getMinutes() < 10 ? '0' : '') + date.getMinutes() + ':' + (date.getSeconds() < 10 ? '0' : '') + date.getSeconds() } page.getPrettyBytes = num => { // MIT License // Copyright (c) Sindre Sorhus (sindresorhus.com) if (!Number.isFinite(num)) { return num } const neg = num < 0 if (neg) { num = -num } if (num < 1) { return `${neg ? '-' : ''}${num}B` } const exponent = Math.min(Math.floor(Math.log10(num) / 3), page.byteUnits.length - 1) const numStr = Number((num / Math.pow(1000, exponent)).toPrecision(3)) const unit = page.byteUnits[exponent] return `${neg ? '-' : ''}${numStr} ${unit}` } page.getUsers = ({ pageNum } = {}, element) => { if (element) { page.isLoading(element, true) } if (pageNum === undefined) { pageNum = 0 } if (!page.permissions.admin) { return swal('An error occurred!', 'You can not do this!', 'error') } const url = `api/users/${pageNum}` axios.get(url).then(function (response) { if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } if (pageNum && (response.data.users.length === 0)) { // Only remove loading class here, since beyond this the entire page will be replaced anyways if (element) { page.isLoading(element, false) } return swal('An error occurred!', 'There are no more users!', 'error') } page.currentView = 'users' page.cache.users = {} const pagination = ` ` const controls = ` ` let allSelected = true page.dom.innerHTML = ` ${pagination}
${controls}
ID Username Uploads Usage File length Group

${pagination} ` const table = document.getElementById('table') for (let i = 0; i < response.data.users.length; i++) { const user = response.data.users[i] const selected = page.selected.users.includes(user.id) if (!selected && allSelected) { allSelected = false } let displayGroup = null for (const group of Object.keys(user.groups)) { if (!user.groups[group]) { break } displayGroup = group } // Server-side explicitly expects either of these two values to consider a user as disabled const enabled = user.enabled !== false && user.enabled !== 0 page.cache.users[user.id] = { username: user.username, groups: user.groups, enabled, displayGroup } const tr = document.createElement('tr') tr.dataset.id = user.id tr.innerHTML = ` ${user.id} ${user.username} ${user.uploadsCount} ${page.getPrettyBytes(user.diskUsage)} ${user.fileLength || 'default'} ${displayGroup} ` table.appendChild(tr) // page.checkboxes.users = Array.from(table.getElementsByClassName('checkbox')) page.checkboxes.users = Array.from(table.querySelectorAll('.checkbox[data-action="select"]')) } if (allSelected && response.data.users.length) { const selectAll = document.getElementById('selectAll') if (selectAll) { selectAll.checked = true } } page.views.users.pageNum = response.data.users.length ? pageNum : 0 }).catch(function (error) { if (element) { page.isLoading(element, false) } console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } page.editUser = function (id) { const user = page.cache.users[id] if (!user) { return } const groupOptions = Object.keys(page.permissions).map((g, i, a) => { const selected = g === user.displayGroup const disabled = !(a[i + 1] && page.permissions[a[i + 1]]) return `` }).join('\n') const div = document.createElement('div') div.innerHTML = `
` swal({ title: 'Edit user', icon: 'info', content: div, buttons: { cancel: true, confirm: { closeModal: false } } }).then(function (value) { if (!value) { return } axios.post('api/users/edit', { id, username: document.getElementById('swalUsername').value, group: document.getElementById('swalGroup').value, enabled: document.getElementById('swalEnabled').checked, resetPassword: document.getElementById('swalResetPassword').checked }).then(function (response) { if (!response) { return } if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } if (response.data.password) { const div = document.createElement('div') div.innerHTML = `

${user.username}'s new password is:

${response.data.password}

` swal({ title: 'Success!', icon: 'success', content: div }) } else if (response.data.name !== user.name) { swal('Success!', `${user.username} was renamed into: ${response.data.name}.`, 'success') } else { swal('Success!', 'The user was edited!', 'success') } page.getUsers(page.views.users) }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } /* page.disableUser = function (id) { swal({ title: 'Are you sure?', text: `You will be disabling a user with the username ${page.cache.users.id.username}!`, icon: 'warning', dangerMode: true, buttons: { cancel: true, confirm: { text: 'Yes, disable them!', closeModal: false } } }).then(function (proceed) { if (!proceed) { return } axios.post('api/users/disable', { id }).then(function (response) { if (!response) { return } if (response.data.success === false) { if (response.data.description === 'No token provided') { return page.verifyToken(page.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Success!', 'The user has been disabled.', 'success') page.getUsers(page.views.users) }).catch(function (error) { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } */ window.onload = function () { // Add 'no-touch' class to non-touch devices if (!('ontouchstart' in document.documentElement)) { document.documentElement.classList.add('no-touch') } const selectedKeys = ['uploads', 'users'] for (const selectedKey of selectedKeys) { const ls = localStorage[LS_KEYS.selected[selectedKey]] if (ls) { page.selected[selectedKey] = JSON.parse(ls) } } page.preparePage() page.clipboardJS = new ClipboardJS('.clipboard-js') page.clipboardJS.on('success', function () { return swal('Copied!', 'The link has been copied to clipboard.', 'success') }) page.clipboardJS.on('error', function (event) { console.error(event) return swal('An error occurred!', 'There was an error when trying to copy the link to clipboard, please check the console for more information.', 'error') }) page.lazyLoad = new LazyLoad() }