/* 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 = `
`
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}
${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 => `${album.name} `)
.join('\n')
panel.selectAlbumContainer.innerHTML = `
Choose an album
Remove from album
${options}
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
List of albums
ID
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.id}
${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
Your current 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')
})
}