/* eslint-disable no-unused-expressions */ /* global swal, axios, ClipboardJS */ const panel = { page: undefined, username: undefined, token: localStorage.token, filesView: localStorage.filesView, clipboardJS: undefined, selectedFiles: [], selectAlbumContainer: undefined, checkboxes: undefined, lastSelected: undefined } panel.preparePage = () => { if (!panel.token) { window.location = 'auth' } panel.verifyToken(panel.token, true) } panel.verifyToken = (token, reloadOnError) => { if (reloadOnError === undefined) { reloadOnError = false } axios.post('api/tokens/verify', { token }) .then(response => { if (response.data.success === false) { swal({ title: 'An error occurred!', text: response.data.description, icon: 'error' }).then(() => { if (reloadOnError) { localStorage.removeItem('token') location.location = 'auth' } }) return } axios.defaults.headers.common.token = token localStorage.token = token panel.token = token panel.username = response.data.username return panel.prepareDashboard() }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.prepareDashboard = () => { panel.page = document.getElementById('page') document.getElementById('auth').style.display = 'none' document.getElementById('dashboard').style.display = 'block' document.getElementById('itemUploads').addEventListener('click', function () { panel.setActiveMenu(this) }) document.getElementById('itemManageGallery').addEventListener('click', function () { panel.setActiveMenu(this) }) document.getElementById('itemFileLength').addEventListener('click', function () { panel.setActiveMenu(this) }) document.getElementById('itemTokens').addEventListener('click', function () { panel.setActiveMenu(this) }) document.getElementById('itemPassword').addEventListener('click', function () { panel.setActiveMenu(this) }) document.getElementById('itemLogout').innerHTML = `Logout ( ${panel.username} )` panel.getAlbumsSidebar() } panel.logout = () => { localStorage.removeItem('token') location.reload('.') } panel.closeModal = () => { document.getElementById('modal').className = 'modal' } panel.isLoading = (element, state) => { if (!element) { return } if (state && !element.className.includes(' is-loading')) { element.className += ' is-loading' } else if (!state && element.className.includes(' is-loading')) { element.className = element.className.replace(' is-loading', '') } } panel.getUploads = (album, page, element) => { if (element) { panel.isLoading(element, true) } if (page === undefined) { page = 0 } let url = 'api/uploads/' + page if (album !== undefined) { url = 'api/album/' + album + '/' + page } axios.get(url).then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } let prevPage = 0 let nextPage = page + 1 if (response.data.files.length < 25) { nextPage = page } if (page > 0) { prevPage = page - 1 } const pagination = ` ` const controls = `
Bulk delete
` let allFilesSelected = true if (panel.filesView === 'thumbs') { panel.page.innerHTML = ` ${pagination}
${controls}
${pagination} ` const table = document.getElementById('table') for (const file of response.data.files) { const selected = panel.selectedFiles.includes(file.id) if (!selected && allFilesSelected) { allFilesSelected = false } const div = document.createElement('div') let displayAlbumOrUser = file.album if (panel.username === 'root') { displayAlbumOrUser = '' if (file.username !== undefined) { displayAlbumOrUser = file.username } } div.className = 'image-container column is-narrow' if (file.thumb !== undefined) { div.innerHTML = `` } else { div.innerHTML = `

.${file.file.split('.').pop()}

` } div.innerHTML += `

${file.name}

${displayAlbumOrUser ? `${displayAlbumOrUser} – ` : ''}${file.size}

` table.appendChild(div) panel.checkboxes = Array.from(table.getElementsByClassName('file-checkbox')) } } else { let albumOrUser = 'Album' if (panel.username === 'root') { albumOrUser = 'User' } panel.page.innerHTML = ` ${pagination}
${controls}
File ${albumOrUser} Size Date

${pagination} ` const table = document.getElementById('table') for (const file of response.data.files) { const selected = panel.selectedFiles.includes(file.id) if (!selected && allFilesSelected) { allFilesSelected = false } const tr = document.createElement('tr') let displayAlbumOrUser = file.album if (panel.username === 'root') { displayAlbumOrUser = '' if (file.username !== undefined) { displayAlbumOrUser = file.username } } tr.innerHTML = ` ${file.name} ${displayAlbumOrUser} ${file.size} ${file.date} ` table.appendChild(tr) panel.checkboxes = Array.from(table.getElementsByClassName('file-checkbox')) } } if (allFilesSelected && response.data.files.length) { const selectAll = document.getElementById('selectAll') if (selectAll) { selectAll.checked = true } } }).catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.setFilesView = (view, album, page, element) => { localStorage.filesView = view panel.filesView = view panel.getUploads(album, page, element) } panel.displayThumbnailModal = thumb => { if (!thumb) { return } document.getElementById('modalImage').src = thumb document.getElementById('modal').className += ' is-active' } panel.selectAllFiles = element => { const table = document.getElementById('table') const checkboxes = table.getElementsByClassName('file-checkbox') for (const checkbox of checkboxes) { const id = parseInt(checkbox.dataset.id) if (isNaN(id)) { continue } if (checkbox.checked !== element.checked) { checkbox.checked = element.checked if (checkbox.checked) { panel.selectedFiles.push(id) } else { panel.selectedFiles.splice(panel.selectedFiles.indexOf(id), 1) } } } if (panel.selectedFiles.length) { localStorage.selectedFiles = JSON.stringify(panel.selectedFiles) } else { localStorage.removeItem('selectedFiles') } element.title = element.checked ? 'Unselect all files' : 'Select all files' } panel.selectInBetween = (element, lastElement) => { if (!element || !lastElement) { return } if (element === lastElement) { return } if (!panel.checkboxes || !panel.checkboxes.length) { return } const thisIndex = panel.checkboxes.indexOf(element) const lastIndex = panel.checkboxes.indexOf(lastElement) const distance = thisIndex - lastIndex if (distance >= -1 && distance <= 1) { return } for (let i = 0; i < panel.checkboxes.length; i++) { if ((thisIndex > lastIndex && i > lastIndex && i < thisIndex) || (thisIndex < lastIndex && i > thisIndex && i < lastIndex)) { panel.checkboxes[i].checked = true panel.selectedFiles.push(parseInt(panel.checkboxes[i].dataset.id)) } } localStorage.selectedFiles = JSON.stringify(panel.selectedFiles) } panel.selectFile = (element, event) => { if (event.shiftKey && panel.lastSelected) { panel.selectInBetween(element, panel.lastSelected) } else { panel.lastSelected = element } const id = parseInt(element.dataset.id) if (isNaN(id)) { return } if (!panel.selectedFiles.includes(id) && element.checked) { panel.selectedFiles.push(id) } else if (panel.selectedFiles.includes(id) && !element.checked) { panel.selectedFiles.splice(panel.selectedFiles.indexOf(id), 1) } if (panel.selectedFiles.length) { localStorage.selectedFiles = JSON.stringify(panel.selectedFiles) } else { localStorage.removeItem('selectedFiles') } } panel.clearSelection = async () => { const count = panel.selectedFiles.length if (!count) { return swal('An error occurred!', 'You have not selected any files.', 'error') } const suffix = `file${count === 1 ? '' : 's'}` const proceed = await swal({ title: 'Are you sure?', text: `You are going to unselect ${count} ${suffix}.`, buttons: true }) if (!proceed) { return } const table = document.getElementById('table') const checkboxes = table.getElementsByClassName('file-checkbox') for (const checkbox of checkboxes) { if (checkbox.checked) { checkbox.checked = false } } panel.selectedFiles = [] localStorage.removeItem('selectedFiles') const selectAll = document.getElementById('selectAll') if (selectAll) { selectAll.checked = false } return swal('Cleared selection!', `Unselected ${count} ${suffix}.`, 'success') } panel.deleteFile = (id, album, page) => { 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(value => { if (!value) { return } axios.post('api/upload/delete', { id }) .then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Deleted!', 'The file has been deleted.', 'success') panel.getUploads(album, page) }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } panel.deleteSelectedFiles = async album => { const count = panel.selectedFiles.length if (!count) { return swal('An error occurred!', 'You have not selected any files.', 'error') } const suffix = `file${count === 1 ? '' : 's'}` const proceed = await 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 } } }) if (!proceed) { return } const bulkdelete = await axios.post('api/upload/bulkdelete', { ids: panel.selectedFiles }) .catch(error => { console.log(error) swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) if (!bulkdelete) { return } if (bulkdelete.data.success === false) { if (bulkdelete.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', bulkdelete.data.description, 'error') } } let deleted = count if (bulkdelete.data.failedids && bulkdelete.data.failedids.length) { deleted -= bulkdelete.data.failedids.length panel.selectedFiles = panel.selectedFiles.filter(id => bulkdelete.data.failedids.includes(id)) } else { panel.selectedFiles = [] } localStorage.selectedFiles = JSON.stringify(panel.selectedFiles) swal('Deleted!', `${deleted} file${deleted === 1 ? ' has' : 's have'} been deleted.`, 'success') return panel.getUploads(album) } panel.addSelectedFilesToAlbum = async album => { const count = panel.selectedFiles.length if (!count) { return swal('An error occurred!', 'You have not selected any files.', 'error') } const failedids = await panel.addToAlbum(panel.selectedFiles, album) if (!failedids) { return } if (failedids.length) { panel.selectedFiles = panel.selectedFiles.filter(id => failedids.includes(id)) } else { panel.selectedFiles = [] } localStorage.selectedFiles = JSON.stringify(panel.selectedFiles) } panel.addToAlbum = async (ids, album) => { const count = ids.length const proceed = await swal({ title: 'Are you sure?', text: `You are about to move ${count} file${count === 1 ? '' : 's'} to an album.`, buttons: { cancel: true, confirm: { text: 'Yes', closeModal: false } } }) if (!proceed) { return } const list = await axios.get('api/albums') .catch(error => { console.log(error) swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) if (!list) { return } if (list.data.success === false) { if (list.data.description === 'No token provided') { panel.verifyToken(panel.token) } else { swal('An error occurred!', list.data.description, 'error') } return } if (!panel.selectAlbumContainer) { // We want to this to be re-usable panel.selectAlbumContainer = document.createElement('div') panel.selectAlbumContainer.id = 'selectAlbum' panel.selectAlbumContainer.className = 'select is-fullwidth' } const options = list.data.albums .map(album => ``) .join('\n') panel.selectAlbumContainer.innerHTML = `

If a file is already in an album, it will be moved.

` const choose = await swal({ content: panel.selectAlbumContainer, buttons: { cancel: true, confirm: { text: 'OK', closeModal: false } } }) if (!choose) { return } const albumid = parseInt(panel.selectAlbumContainer.getElementsByTagName('select')[0].value) if (isNaN(albumid)) { swal('An error occurred!', 'You did not choose an album.', 'error') return } const add = await axios.post('api/albums/addfiles', { ids, albumid }) .catch(error => { console.log(error) swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) if (!add) { return } if (add.data.success === false) { if (add.data.description === 'No token provided') { panel.verifyToken(panel.token) } else { swal('An error occurred!', add.data.description, 'error') } return } let added = ids.length if (add.data.failedids && add.data.failedids.length) { added -= add.data.failedids.length } const suffix = `file${ids.length === 1 ? '' : 's'}` if (!added) { swal('An error occurred!', `Could not add the ${suffix} to the album.`, 'error') return } swal('Woohoo!', `Successfully ${albumid < 0 ? 'removed' : 'added'} ${added} ${suffix} ${albumid < 0 ? 'from' : 'to'} the album.`, 'success') panel.getUploads(album) return add.data.failedids } panel.getAlbums = () => { axios.get('api/albums').then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } panel.page.innerHTML = `

Create new album

Submit

List of albums

Name Files Created at Public link
` const table = document.getElementById('table') for (const album of response.data.albums) { const tr = document.createElement('tr') tr.innerHTML = ` ${album.name} ${album.files} ${album.date} ${album.identifier} ` table.appendChild(tr) } document.getElementById('submitAlbum').addEventListener('click', function () { panel.submitAlbum(this) }) }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.renameAlbum = id => { swal({ title: 'Rename album', text: 'New name you want to give the album:', icon: 'info', content: { element: 'input', attributes: { placeholder: 'My super album' } }, buttons: { cancel: true, confirm: { closeModal: false } } }).then(value => { if (!value) { return swal.close() } axios.post('api/albums/rename', { id, name: value }) .then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else if (response.data.description === 'Name already in use') { swal.showInputError('That name is already in use!') } else { swal('An error occurred!', response.data.description, 'error') } return } swal('Success!', 'Your album was renamed to: ' + value, 'success') panel.getAlbumsSidebar() panel.getAlbums() }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } panel.deleteAlbum = id => { swal({ title: 'Are you sure?', text: 'This won\'t delete your files, only the album!', icon: 'warning', dangerMode: true, buttons: { cancel: true, confirm: { text: 'Yes, delete it!', closeModal: false }, purge: { text: 'Umm, delete the files too please?', value: 'purge', className: 'swal-button--danger', closeModal: false } } }).then(value => { if (!value) { return } axios.post('api/albums/delete', { id, purge: value === 'purge' }) .then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Deleted!', 'Your album has been deleted.', 'success') panel.getAlbumsSidebar() panel.getAlbums() }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) }) } panel.submitAlbum = element => { panel.isLoading(element, true) axios.post('api/albums', { name: document.getElementById('albumName').value }) .then(async response => { panel.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal('Woohoo!', 'Album was added successfully', 'success') panel.getAlbumsSidebar() panel.getAlbums() }) .catch(error => { console.log(error) panel.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.getAlbumsSidebar = () => { axios.get('api/albums/sidebar') .then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.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 (const album of response.data.albums) { const li = document.createElement('li') const a = document.createElement('a') a.id = album.id a.innerHTML = album.name a.addEventListener('click', function () { panel.getAlbum(this) }) li.appendChild(a) albumsContainer.appendChild(li) } }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.getAlbum = album => { panel.setActiveMenu(album) panel.getUploads(album.id) } panel.changeFileLength = () => { axios.get('api/filelength/config') .then(response => { if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } panel.page.innerHTML = `

File name length

Default file name length is ${response.data.config.default} characters. ${response.data.config.userChangeable ? `Range allowed for user is ${response.data.config.min} to ${response.data.config.max} characters.` : 'Changing file name length is disabled at the moment.'}

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

Manage your token

` document.getElementById('getNewToken').addEventListener('click', function () { panel.getNewToken(this) }) }) .catch(error => { console.log(error) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.getNewToken = element => { panel.isLoading(element, true) axios.post('api/tokens/change') .then(response => { panel.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal({ title: 'Woohoo!', text: 'Your token was successfully changed.', icon: 'success' }).then(() => { localStorage.token = response.data.token location.reload() }) }) .catch(error => { console.log(error) panel.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.changePassword = () => { panel.page.innerHTML = `

Change your password

` document.getElementById('sendChangePassword').addEventListener('click', function () { if (document.getElementById('password').value === document.getElementById('passwordConfirm').value) { panel.sendNewPassword(document.getElementById('password').value, this) } else { swal({ title: 'Password mismatch!', text: 'Your passwords do not match, please try again.', icon: 'error' }).then(() => { panel.changePassword() }) } }) } panel.sendNewPassword = (pass, element) => { panel.isLoading(element, true) axios.post('api/password/change', { password: pass }) .then(response => { panel.isLoading(element, false) if (response.data.success === false) { if (response.data.description === 'No token provided') { return panel.verifyToken(panel.token) } else { return swal('An error occurred!', response.data.description, 'error') } } swal({ title: 'Woohoo!', text: 'Your password was successfully changed.', icon: 'success' }).then(() => { location.reload() }) }) .catch(error => { console.log(error) panel.isLoading(element, false) return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error') }) } panel.setActiveMenu = item => { const menu = document.getElementById('menu') const items = menu.getElementsByTagName('a') for (const item of items) { item.className = '' } item.className = 'is-active' } window.onload = () => { // Add 'no-touch' class to non-touch devices if (!('ontouchstart' in document.documentElement)) { document.documentElement.className += ' no-touch' } const selectedFiles = localStorage.selectedFiles if (selectedFiles) { panel.selectedFiles = JSON.parse(selectedFiles) } panel.preparePage() panel.clipboardJS = new ClipboardJS('.clipboard-js') panel.clipboardJS.on('success', () => { return swal('Copied!', 'The link has been copied to clipboard.', 'success') }) panel.clipboardJS.on('error', 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') }) }