2018-04-29 12:47:24 +00:00
/* global swal, axios, Dropzone, ClipboardJS, LazyLoad */
2017-01-14 09:16:47 +00:00
2018-10-09 19:52:41 +00:00
const page = {
2018-04-29 12:47:24 +00:00
// user token
2018-03-28 11:36:28 +00:00
token : localStorage . token ,
2018-04-29 12:47:24 +00:00
// configs from api/check
private : null ,
enableUserAccounts : null ,
maxFileSize : null ,
2018-05-09 08:41:30 +00:00
chunkSize : null ,
2018-04-29 12:47:24 +00:00
// store album id that will be used with upload requests
album : null ,
2018-05-06 14:14:57 +00:00
albumSelect : null ,
2018-05-11 14:34:13 +00:00
previewTemplate : null ,
2018-05-06 14:14:57 +00:00
2018-04-29 12:47:24 +00:00
dropzone : null ,
clipboardJS : null ,
2018-10-18 13:26:40 +00:00
lazyLoad : null ,
2018-01-23 20:06:30 +00:00
2018-10-18 13:26:40 +00:00
imageExtensions : [ '.webp' , '.jpg' , '.jpeg' , '.bmp' , '.gif' , '.png' ]
}
2018-01-23 20:06:30 +00:00
2018-07-14 03:42:18 +00:00
page . checkIfPublic = function ( ) {
2018-10-09 19:52:41 +00:00
axios . get ( 'api/check' ) . then ( function ( response ) {
page . private = response . data . private
page . enableUserAccounts = response . data . enableUserAccounts
page . maxFileSize = response . data . maxFileSize
page . chunkSize = response . data . chunkSize
page . preparePage ( )
} ) . catch ( function ( error ) {
console . log ( error )
const button = document . getElementById ( 'loginToUpload' )
button . classList . remove ( 'is-loading' )
button . innerText = 'Error occurred. Reload the page?'
return swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
} )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . preparePage = function ( ) {
2018-04-29 12:47:24 +00:00
if ( page . private ) {
if ( page . token ) {
return page . verifyToken ( page . token , true )
2018-01-24 15:31:23 +00:00
} else {
2018-10-09 19:52:41 +00:00
const button = document . getElementById ( 'loginToUpload' )
2018-03-28 20:05:01 +00:00
button . href = 'auth'
2018-05-06 14:14:57 +00:00
button . classList . remove ( 'is-loading' )
2018-04-03 18:54:42 +00:00
2018-04-29 12:47:24 +00:00
if ( page . enableUserAccounts ) {
button . innerText = 'Anonymous upload is disabled. Log in to page.'
2018-04-03 18:54:42 +00:00
} else {
2018-04-29 12:47:24 +00:00
button . innerText = 'Running in private mode. Log in to page.'
2018-04-03 18:54:42 +00:00
}
2018-01-24 15:31:23 +00:00
}
} else {
2018-04-29 12:47:24 +00:00
return page . prepareUpload ( )
2018-01-23 20:06:30 +00:00
}
}
2018-07-14 03:42:18 +00:00
page . verifyToken = function ( token , reloadOnError ) {
2018-01-23 20:06:30 +00:00
if ( reloadOnError === undefined ) { reloadOnError = false }
2018-10-09 19:52:41 +00:00
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 ( 'token' )
location . reload ( )
} )
}
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
localStorage . token = token
page . token = token
return page . prepareUpload ( )
} ) . 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' )
} )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . prepareUpload = function ( ) {
2018-01-23 20:06:30 +00:00
// I think this fits best here because we need to check for a valid token before we can get the albums
2018-04-29 12:47:24 +00:00
if ( page . token ) {
2018-05-06 14:14:57 +00:00
page . albumSelect = document . getElementById ( 'albumSelect' )
2018-01-23 20:06:30 +00:00
2018-07-14 03:42:18 +00:00
page . albumSelect . addEventListener ( 'change' , function ( ) {
2018-05-06 14:14:57 +00:00
page . album = parseInt ( page . albumSelect . value )
2018-01-23 20:06:30 +00:00
} )
2018-05-06 14:14:57 +00:00
page . prepareAlbums ( )
// Display the album selection
document . getElementById ( 'albumDiv' ) . style . display = 'flex'
2018-01-23 20:06:30 +00:00
}
2018-10-09 19:52:41 +00:00
document . getElementById ( 'maxFileSize' ) . innerHTML = ` Maximum upload size per file is ${ page . maxFileSize } `
2018-01-23 20:06:30 +00:00
document . getElementById ( 'loginToUpload' ) . style . display = 'none'
2018-04-29 12:47:24 +00:00
if ( ! page . token && page . enableUserAccounts ) {
2018-03-28 11:36:28 +00:00
document . getElementById ( 'loginLinkText' ) . innerHTML = 'Create an account and keep track of your uploads'
}
2018-01-23 20:06:30 +00:00
2018-10-09 19:52:41 +00:00
const previewNode = document . querySelector ( '#tpl' )
2018-05-11 14:34:13 +00:00
page . previewTemplate = previewNode . innerHTML
previewNode . parentNode . removeChild ( previewNode )
2018-01-23 20:06:30 +00:00
2018-04-29 12:47:24 +00:00
page . prepareDropzone ( )
2018-05-11 14:34:13 +00:00
2018-10-09 19:52:41 +00:00
const tabs = document . getElementById ( 'tabs' )
2018-05-11 14:34:13 +00:00
if ( tabs ) {
tabs . style . display = 'flex'
2018-10-09 19:52:41 +00:00
const items = tabs . getElementsByTagName ( 'li' )
for ( let i = 0 ; i < items . length ; i ++ ) {
2018-07-14 04:35:31 +00:00
items [ i ] . addEventListener ( 'click' , function ( ) {
2018-05-11 14:34:13 +00:00
page . setActiveTab ( this . dataset . id )
} )
}
document . getElementById ( 'uploadUrls' ) . addEventListener ( 'click' , function ( ) {
page . uploadUrls ( this )
} )
page . setActiveTab ( 'tab-files' )
} else {
document . getElementById ( 'tab-files' ) . style . display = 'block'
}
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . prepareAlbums = function ( ) {
2018-10-09 19:52:41 +00:00
const option = document . createElement ( 'option' )
2018-05-06 14:14:57 +00:00
option . value = ''
option . innerHTML = 'Upload to album'
option . disabled = true
option . selected = true
page . albumSelect . appendChild ( option )
2018-10-09 19:52:41 +00:00
axios . get ( 'api/albums' , {
headers : {
token : page . token
}
} ) . then ( function ( response ) {
if ( response . data . success === false ) {
return swal ( 'An error occurred!' , response . data . description , 'error' )
}
2018-05-06 14:14:57 +00:00
2018-10-09 19:52:41 +00:00
// If the user doesn't have any albums we don't really need to display
// an album selection
if ( ! response . data . albums . length ) { return }
// Loop through the albums and create an option for each album
for ( let i = 0 ; i < response . data . albums . length ; i ++ ) {
const album = response . data . albums [ i ]
const option = document . createElement ( 'option' )
option . value = album . id
option . innerHTML = album . name
page . albumSelect . appendChild ( option )
}
} ) . 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' )
} )
2018-05-06 14:14:57 +00:00
}
2018-07-14 03:42:18 +00:00
page . setActiveTab = function ( activeId ) {
2018-10-09 19:52:41 +00:00
const items = document . getElementById ( 'tabs' ) . getElementsByTagName ( 'li' )
for ( let i = 0 ; i < items . length ; i ++ ) {
const tabId = items [ i ] . dataset . id
2018-05-11 14:34:13 +00:00
if ( tabId === activeId ) {
2018-07-14 04:35:31 +00:00
items [ i ] . classList . add ( 'is-active' )
2018-05-11 14:34:13 +00:00
document . getElementById ( tabId ) . style . display = 'block'
} else {
2018-07-14 04:35:31 +00:00
items [ i ] . classList . remove ( 'is-active' )
2018-05-11 14:34:13 +00:00
document . getElementById ( tabId ) . style . display = 'none'
}
}
}
2018-07-14 03:42:18 +00:00
page . prepareDropzone = function ( ) {
2018-10-09 19:52:41 +00:00
const tabDiv = document . getElementById ( 'tab-files' )
const div = document . createElement ( 'div' )
2018-05-11 14:34:13 +00:00
div . className = 'control is-expanded'
2018-10-09 19:52:41 +00:00
div . innerHTML = `
< div id = "dropzone" class = "button is-danger is-fullwidth is-unselectable" >
< span class = "icon" >
< i class = "icon-upload-cloud" > < / i >
< / s p a n >
< span > Click here or drag and drop files < / s p a n >
< / d i v >
`
2018-10-18 13:26:40 +00:00
tabDiv . querySelector ( '.dz-container' ) . appendChild ( div )
2018-09-04 15:49:37 +00:00
2018-10-18 13:26:40 +00:00
const previewsContainer = tabDiv . querySelector ( '#tab-files .field.uploads' )
2018-04-29 12:47:24 +00:00
page . dropzone = new Dropzone ( '#dropzone' , {
2018-01-24 15:31:23 +00:00
url : 'api/upload' ,
2018-01-23 20:06:30 +00:00
paramName : 'files[]' ,
2018-04-29 12:47:24 +00:00
maxFilesize : parseInt ( page . maxFileSize ) ,
2018-01-23 20:06:30 +00:00
parallelUploads : 2 ,
uploadMultiple : false ,
2018-10-09 19:52:41 +00:00
previewsContainer ,
2018-05-11 14:34:13 +00:00
previewTemplate : page . previewTemplate ,
2018-01-23 20:06:30 +00:00
createImageThumbnails : false ,
maxFiles : 1000 ,
autoProcessQueue : true ,
2018-04-29 12:47:24 +00:00
headers : { token : page . token } ,
2018-05-09 08:41:30 +00:00
chunking : Boolean ( page . chunkSize ) ,
chunkSize : parseInt ( page . chunkSize ) * 1000000 , // 1000000 B = 1 MB,
2018-03-28 11:36:28 +00:00
parallelChunkUploads : false , // when set to true, sometimes it often hangs with hundreds of parallel uploads
2018-10-09 19:52:41 +00:00
chunksUploaded ( file , done ) {
2018-03-28 11:36:28 +00:00
file . previewElement . querySelector ( '.progress' ) . setAttribute ( 'value' , 100 )
2018-04-03 18:54:42 +00:00
file . previewElement . querySelector ( '.progress' ) . innerHTML = '100%'
2018-03-28 11:36:28 +00:00
2018-10-09 19:52:41 +00:00
return axios . post ( 'api/upload/finishchunks' , {
// The API supports an array of multiple files
files : [ {
uuid : file . upload . uuid ,
original : file . name ,
size : file . size ,
type : file . type ,
count : file . upload . totalChunkCount ,
albumid : page . album
} ]
} , {
headers : {
token : page . token
}
} ) . then ( function ( response ) {
file . previewElement . querySelector ( '.progress' ) . style . display = 'none'
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
if ( response . data . success === false ) {
file . previewElement . querySelector ( '.error' ) . innerHTML = response . data . description
}
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
if ( response . data . files && response . data . files [ 0 ] ) {
page . updateTemplate ( file , response . data . files [ 0 ] )
}
return done ( )
} ) . catch ( function ( error ) {
return {
success : false ,
description : error . toString ( )
}
} )
2018-01-23 20:06:30 +00:00
}
} )
2018-07-14 03:42:18 +00:00
page . dropzone . on ( 'addedfile' , function ( file ) {
2018-05-12 22:13:26 +00:00
tabDiv . getElementsByClassName ( 'uploads' ) [ 0 ] . style . display = 'block'
2018-05-11 14:34:13 +00:00
file . previewElement . querySelector ( '.name' ) . innerHTML = file . name
2018-03-28 11:36:28 +00:00
} )
// Add the selected albumid, if an album is selected, as a header
2018-07-14 03:42:18 +00:00
page . dropzone . on ( 'sending' , function ( file , xhr ) {
2018-04-05 12:54:24 +00:00
if ( file . upload . chunked ) { return }
2018-04-29 12:47:24 +00:00
if ( page . album ) { xhr . setRequestHeader ( 'albumid' , page . album ) }
2018-03-28 11:36:28 +00:00
} )
2018-01-23 20:06:30 +00:00
// Update the total progress bar
2018-07-14 03:42:18 +00:00
page . dropzone . on ( 'uploadprogress' , function ( file , progress ) {
2018-03-28 17:40:50 +00:00
if ( file . upload . chunked && progress === 100 ) { return }
2018-01-23 20:06:30 +00:00
file . previewElement . querySelector ( '.progress' ) . setAttribute ( 'value' , progress )
2018-10-09 19:52:41 +00:00
file . previewElement . querySelector ( '.progress' ) . innerHTML = ` ${ progress } % `
2018-01-23 20:06:30 +00:00
} )
2018-07-14 03:42:18 +00:00
page . dropzone . on ( 'success' , function ( file , response ) {
2018-03-28 17:40:50 +00:00
if ( ! response ) { return }
2018-05-11 14:34:13 +00:00
file . previewElement . querySelector ( '.progress' ) . style . display = 'none'
// file.previewElement.querySelector('.name').innerHTML = file.name
2018-01-23 20:06:30 +00:00
if ( response . success === false ) {
2018-05-11 14:34:13 +00:00
file . previewElement . querySelector ( '.error' ) . innerHTML = response . description
2018-01-23 20:06:30 +00:00
}
2018-04-29 12:47:24 +00:00
if ( response . files && response . files [ 0 ] ) {
page . updateTemplate ( file , response . files [ 0 ] )
2018-04-05 10:21:51 +00:00
}
2018-03-24 19:47:41 +00:00
} )
2018-01-23 20:06:30 +00:00
2018-07-14 03:42:18 +00:00
page . dropzone . on ( 'error' , function ( file , error ) {
2018-05-11 14:34:13 +00:00
file . previewElement . querySelector ( '.progress' ) . style . display = 'none'
file . previewElement . querySelector ( '.name' ) . innerHTML = file . name
file . previewElement . querySelector ( '.error' ) . innerHTML = error
2018-01-23 20:06:30 +00:00
} )
2018-10-08 19:30:22 +00:00
if ( typeof page . prepareShareX === 'function' ) { page . prepareShareX ( ) }
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . uploadUrls = function ( button ) {
2018-10-09 19:52:41 +00:00
const tabDiv = document . getElementById ( 'tab-urls' )
2018-05-11 14:34:13 +00:00
if ( ! tabDiv ) { return }
if ( button . classList . contains ( 'is-loading' ) ) { return }
button . classList . add ( 'is-loading' )
2018-09-07 15:02:04 +00:00
function done ( error ) {
2018-07-14 03:42:18 +00:00
if ( error ) { swal ( 'An error occurred!' , error , 'error' ) }
button . classList . remove ( 'is-loading' )
}
2018-09-07 15:02:04 +00:00
function run ( ) {
2018-10-09 19:52:41 +00:00
const albumid = page . album
const previewsContainer = tabDiv . getElementsByClassName ( 'uploads' ) [ 0 ]
const urls = document . getElementById ( 'urls' ) . value
2018-05-12 22:13:26 +00:00
. split ( /\r?\n/ )
2018-07-14 03:42:18 +00:00
. filter ( function ( url ) { return url . trim ( ) . length } )
2018-05-12 22:13:26 +00:00
document . getElementById ( 'urls' ) . value = urls . join ( '\n' )
if ( ! urls . length ) {
// eslint-disable-next-line prefer-promise-reject-errors
2018-07-14 03:42:18 +00:00
return done ( 'You have not entered any URLs.' )
2018-05-12 22:13:26 +00:00
}
tabDiv . getElementsByClassName ( 'uploads' ) [ 0 ] . style . display = 'block'
2018-10-09 19:52:41 +00:00
const files = urls . map ( function ( url ) {
const previewTemplate = document . createElement ( 'template' )
2018-05-11 14:34:13 +00:00
previewTemplate . innerHTML = page . previewTemplate . trim ( )
2018-10-09 19:52:41 +00:00
const previewElement = previewTemplate . content . firstChild
2018-05-11 15:10:49 +00:00
previewElement . querySelector ( '.name' ) . innerHTML = url
previewsContainer . appendChild ( previewElement )
2018-09-04 15:49:37 +00:00
return {
2018-10-09 19:52:41 +00:00
url ,
previewElement
2018-09-04 15:49:37 +00:00
}
2018-05-11 14:34:13 +00:00
} )
2018-09-07 15:02:04 +00:00
function post ( i ) {
2018-07-14 03:42:18 +00:00
if ( i === files . length ) { return done ( ) }
2018-10-09 19:52:41 +00:00
const file = files [ i ]
2018-07-14 03:42:18 +00:00
2018-09-07 15:02:04 +00:00
function posted ( result ) {
2018-07-14 03:42:18 +00:00
file . previewElement . querySelector ( '.progress' ) . style . display = 'none'
if ( result . success ) {
page . updateTemplate ( file , result . files [ 0 ] )
} else {
file . previewElement . querySelector ( '.error' ) . innerHTML = result . description
}
return post ( i + 1 )
}
2018-10-09 19:52:41 +00:00
axios . post ( 'api/upload' , {
urls : [ file . url ]
} , {
headers : {
token : page . token ,
albumid
}
} ) . then ( function ( response ) {
return posted ( response . data )
} ) . catch ( function ( error ) {
return posted ( {
success : false ,
description : error . toString ( )
2018-05-11 14:34:13 +00:00
} )
2018-10-09 19:52:41 +00:00
} )
2018-05-11 14:34:13 +00:00
}
2018-07-14 03:42:18 +00:00
return post ( 0 )
}
return run ( )
2018-05-11 14:34:13 +00:00
}
2018-07-14 03:42:18 +00:00
page . updateTemplate = function ( file , response ) {
2018-04-29 12:47:24 +00:00
if ( ! response . url ) { return }
2018-10-09 19:52:41 +00:00
const a = file . previewElement . querySelector ( '.link > a' )
const clipboard = file . previewElement . querySelector ( '.clipboard-mobile > .clipboard-js' )
2018-04-29 12:47:24 +00:00
a . href = a . innerHTML = clipboard . dataset [ 'clipboardText' ] = response . url
clipboard . parentElement . style . display = 'block'
2018-03-28 20:05:01 +00:00
2018-10-09 19:52:41 +00:00
const exec = /.[\w]+(\?|$)/ . exec ( response . url )
2018-10-18 13:26:40 +00:00
if ( exec && exec [ 0 ] && page . imageExtensions . includes ( exec [ 0 ] . toLowerCase ( ) ) ) {
2018-10-09 19:52:41 +00:00
const img = file . previewElement . querySelector ( 'img' )
2018-04-29 12:47:24 +00:00
img . setAttribute ( 'alt' , response . name || '' )
img . dataset [ 'src' ] = response . url
img . onerror = function ( ) { this . style . display = 'none' } // hide webp in firefox and ie
2018-10-18 13:40:47 +00:00
page . lazyLoad . update ( file . previewElement . querySelectorAll ( 'img' ) )
2018-03-28 11:36:28 +00:00
}
}
2018-07-14 03:42:18 +00:00
page . createAlbum = function ( ) {
2018-10-09 19:52:41 +00:00
const div = document . createElement ( 'div' )
div . innerHTML = `
< div class = "field" >
< label class = "label" > Album name < / l a b e l >
< div class = "controls" >
< input id = "swalName" class = "input" type = "text" placeholder = "My super album" >
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< label class = "checkbox" >
< input id = "swalDownload" type = "checkbox" checked >
Enable download
< / l a b e l >
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< label class = "checkbox" >
< input id = "swalPublic" type = "checkbox" checked >
Enable public link
< / l a b e l >
< / d i v >
< / d i v >
`
2018-09-04 15:49:37 +00:00
2018-07-14 03:42:18 +00:00
swal ( {
2018-05-06 14:14:57 +00:00
title : 'Create new album' ,
icon : 'info' ,
content : div ,
buttons : {
cancel : true ,
confirm : {
closeModal : false
}
}
2018-10-09 19:52:41 +00:00
} ) . then ( function ( value ) {
if ( ! value ) { return }
const name = document . getElementById ( 'swalName' ) . value
axios . post ( 'api/albums' , {
name ,
download : document . getElementById ( 'swalDownload' ) . checked ,
public : document . getElementById ( 'swalPublic' ) . checked
} , {
headers : {
token : page . token
}
} ) . then ( function ( response ) {
if ( response . data . success === false ) {
return swal ( 'An error occurred!' , response . data . description , 'error' )
}
const option = document . createElement ( 'option' )
option . value = response . data . id
option . innerHTML = name
page . albumSelect . appendChild ( option )
swal ( 'Woohoo!' , 'Album was created successfully' , 'success' )
} ) . 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' )
2018-07-14 03:42:18 +00:00
} )
2018-10-09 19:52:41 +00:00
} )
2018-05-06 14:14:57 +00:00
}
2018-01-23 18:00:55 +00:00
// Handle image paste event
2018-07-14 03:42:18 +00:00
window . addEventListener ( 'paste' , function ( event ) {
2018-10-09 19:52:41 +00:00
const items = ( event . clipboardData || event . originalEvent . clipboardData ) . items
for ( const index in items ) {
const item = items [ index ]
2018-01-23 20:06:30 +00:00
if ( item . kind === 'file' ) {
2018-10-09 19:52:41 +00:00
const blob = item . getAsFile ( )
const file = new File ( [ blob ] , ` pasted-image. ${ blob . type . match ( /(?:[^/]*\/)([^;]*)/ ) [ 1 ] } ` )
2018-01-23 20:06:30 +00:00
file . type = blob . type
2018-04-29 12:47:24 +00:00
page . dropzone . addFile ( file )
2018-01-23 20:06:30 +00:00
}
}
} )
2018-07-14 03:42:18 +00:00
window . onload = function ( ) {
2018-04-29 12:47:24 +00:00
page . checkIfPublic ( )
2018-03-28 20:05:01 +00:00
2018-04-29 12:47:24 +00:00
page . clipboardJS = new ClipboardJS ( '.clipboard-js' )
2018-03-28 20:05:01 +00:00
2018-07-14 03:42:18 +00:00
page . clipboardJS . on ( 'success' , function ( ) {
2018-03-28 20:05:01 +00:00
return swal ( 'Copied!' , 'The link has been copied to clipboard.' , 'success' )
} )
2018-07-14 03:42:18 +00:00
page . clipboardJS . on ( 'error' , function ( event ) {
2018-03-28 20:05:01 +00:00
console . error ( event )
2018-03-30 02:39:53 +00:00
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' )
2018-03-28 20:05:01 +00:00
} )
2018-04-29 12:47:24 +00:00
2018-10-18 13:26:40 +00:00
page . lazyLoad = new LazyLoad ( {
elements _selector : '.field.uploads img'
} )
2018-07-17 03:21:04 +00:00
document . getElementById ( 'createAlbum' ) . addEventListener ( 'click' , function ( ) {
page . createAlbum ( )
} )
2018-01-23 20:06:30 +00:00
}