2018-04-29 12:47:24 +00:00
/* global swal, axios, ClipboardJS, LazyLoad */
2018-01-23 20:06:30 +00:00
2019-01-03 04:49:56 +00:00
const lsKeys = {
2018-10-09 19:52:41 +00:00
token : 'token' ,
viewType : {
2019-01-03 04:49:56 +00:00
uploads : 'viewTypeUploads' ,
uploadsAll : 'viewTypeUploadsAll'
2018-10-09 19:52:41 +00:00
} ,
selected : {
2019-01-03 04:49:56 +00:00
uploads : 'selectedUploads' ,
uploadsAll : 'selectedUploadsAll' ,
users : 'selectedUsers'
2019-09-02 10:24:04 +00:00
}
2018-10-09 19:52:41 +00:00
}
const page = {
2018-04-29 12:47:24 +00:00
// #page
dom : null ,
// user token
2019-01-03 04:49:56 +00:00
token : localStorage [ lsKeys . token ] ,
2018-10-09 19:52:41 +00:00
// from api/tokens/verify
username : null ,
permissions : null ,
currentView : null ,
views : {
// config of uploads view
uploads : {
2019-01-03 04:49:56 +00:00
type : localStorage [ lsKeys . viewType . uploads ] ,
2018-10-09 19:52:41 +00:00
album : null , // album's id
2019-01-03 04:49:56 +00:00
pageNum : null // page num
} ,
// config of uploads view (all)
uploadsAll : {
type : localStorage [ lsKeys . viewType . uploadsAll ] ,
2019-06-17 19:34:15 +00:00
filters : null , // uploads' filters
2018-10-09 19:52:41 +00:00
pageNum : null , // page num
2019-01-03 04:49:56 +00:00
all : true
2018-10-09 19:52:41 +00:00
} ,
// config of users view
users : {
pageNum : null
}
} ,
// id of selected items (shared across pages and will be synced with localStorage)
selected : {
uploads : [ ] ,
2019-01-03 04:49:56 +00:00
uploadsAll : [ ] ,
2018-10-09 19:52:41 +00:00
users : [ ]
} ,
checkboxes : {
uploads : [ ] ,
2019-01-03 04:49:56 +00:00
uploadsAll : [ ] ,
2018-10-09 19:52:41 +00:00
users : [ ]
} ,
lastSelected : {
upload : null ,
2019-01-03 04:49:56 +00:00
uploadsAll : null ,
2018-10-09 19:52:41 +00:00
user : null
} ,
2018-04-29 12:47:24 +00:00
2018-05-05 19:44:58 +00:00
// select album dom for dialogs/modals
2018-04-29 12:47:24 +00:00
selectAlbumContainer : null ,
2018-10-09 19:52:41 +00:00
// cache for dialogs/modals
cache : {
uploads : { } ,
albums : { } ,
users : { }
} ,
2018-04-29 12:47:24 +00:00
clipboardJS : null ,
2018-10-08 18:54:16 +00:00
lazyLoad : null ,
2018-10-18 13:26:40 +00:00
imageExtensions : [ '.webp' , '.jpg' , '.jpeg' , '.bmp' , '.gif' , '.png' ] ,
2018-12-04 11:58:53 +00:00
fadingIn : null
2018-03-28 11:36:28 +00:00
}
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 . token ) {
2018-01-24 15:31:23 +00:00
window . location = 'auth'
2018-04-29 12:47:24 +00:00
return
2018-01-23 20:06:30 +00:00
}
2018-04-29 12:47:24 +00:00
page . verifyToken ( page . token , true )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . verifyToken = function ( token , reloadOnError ) {
2018-10-09 19:52:41 +00:00
axios . post ( 'api/tokens/verify' , { token } ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
return swal ( {
title : 'An error occurred!' ,
text : response . data . description ,
icon : 'error'
} ) . then ( function ( ) {
2018-12-18 17:01:28 +00:00
if ( ! reloadOnError ) return
2019-01-03 04:49:56 +00:00
localStorage . removeItem ( lsKeys . token )
2018-10-09 19:52:41 +00:00
location . location = 'auth'
} )
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
axios . defaults . headers . common . token = token
2019-01-03 04:49:56 +00:00
localStorage [ lsKeys . token ] = token
2018-10-09 19:52:41 +00:00
page . token = token
page . username = response . data . username
page . permissions = response . data . permissions
page . prepareDashboard ( )
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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 . prepareDashboard = function ( ) {
2019-08-20 02:16:34 +00:00
page . dom = document . querySelector ( '#page' )
2018-09-04 15:49:37 +00:00
page . dom . addEventListener ( 'click' , page . domClick , true )
2019-08-26 22:00:57 +00:00
page . dom . addEventListener ( 'submit' , function ( event ) {
const element = event . target
if ( element && element . classList . contains ( 'prevent-default' ) )
return event . preventDefault ( )
} , true )
2019-08-20 02:16:34 +00:00
document . querySelector ( '#dashboard' ) . style . display = 'block'
2018-01-23 20:06:30 +00:00
2018-10-09 19:52:41 +00:00
if ( page . permissions . moderator ) {
2019-09-01 19:23:16 +00:00
document . querySelector ( '#itemLabelAdmin' ) . style . display = 'block'
document . querySelector ( '#itemListAdmin' ) . style . display = 'block'
2019-08-20 02:16:34 +00:00
const itemManageUploads = document . querySelector ( '#itemManageUploads' )
2018-10-09 19:52:41 +00:00
itemManageUploads . addEventListener ( 'click' , function ( ) {
page . setActiveMenu ( this )
page . getUploads ( { all : true } )
} )
}
if ( page . permissions . admin ) {
2019-08-20 02:16:34 +00:00
const itemServerStats = document . querySelector ( '#itemServerStats' )
2019-04-05 17:32:52 +00:00
itemServerStats . addEventListener ( 'click' , function ( ) {
page . setActiveMenu ( this )
page . getServerStats ( )
} )
2019-08-20 02:16:34 +00:00
const itemManageUsers = document . querySelector ( '#itemManageUsers' )
2018-10-09 19:52:41 +00:00
itemManageUsers . addEventListener ( 'click' , function ( ) {
page . setActiveMenu ( this )
page . getUsers ( )
} )
2019-09-01 19:23:16 +00:00
} else {
document . querySelector ( '#itemServerStats' ) . style . display = 'none'
document . querySelector ( '#itemManageUsers' ) . style . display = 'none'
2018-10-09 19:52:41 +00:00
}
2019-08-20 02:16:34 +00:00
document . querySelector ( '#itemUploads' ) . addEventListener ( 'click' , function ( ) {
2018-04-29 12:47:24 +00:00
page . setActiveMenu ( this )
2018-10-09 19:52:41 +00:00
page . getUploads ( { all : false } )
2018-01-23 20:06:30 +00:00
} )
2019-08-20 02:16:34 +00:00
document . querySelector ( '#itemDeleteByNames' ) . addEventListener ( 'click' , function ( ) {
2018-05-05 19:44:58 +00:00
page . setActiveMenu ( this )
2018-07-17 03:21:04 +00:00
page . deleteByNames ( )
2018-05-05 19:44:58 +00:00
} )
2019-08-20 02:16:34 +00:00
document . querySelector ( '#itemManageGallery' ) . addEventListener ( 'click' , function ( ) {
2018-04-29 12:47:24 +00:00
page . setActiveMenu ( this )
2018-07-17 03:21:04 +00:00
page . getAlbums ( )
2018-01-23 20:06:30 +00:00
} )
2019-08-20 02:16:34 +00:00
document . querySelector ( '#itemTokens' ) . addEventListener ( 'click' , function ( ) {
2018-04-29 12:47:24 +00:00
page . setActiveMenu ( this )
2018-07-17 03:21:04 +00:00
page . changeToken ( )
2018-01-23 20:06:30 +00:00
} )
2019-08-20 02:16:34 +00:00
document . querySelector ( '#itemPassword' ) . addEventListener ( 'click' , function ( ) {
2018-04-29 12:47:24 +00:00
page . setActiveMenu ( this )
2018-07-17 03:21:04 +00:00
page . changePassword ( )
2018-01-23 20:06:30 +00:00
} )
2019-08-20 02:16:34 +00:00
const logoutBtn = document . querySelector ( '#itemLogout' )
2018-07-17 03:21:04 +00:00
logoutBtn . addEventListener ( 'click' , function ( ) {
page . logout ( )
} )
2018-10-09 19:52:41 +00:00
logoutBtn . innerHTML = ` Logout ( ${ page . username } ) `
2018-01-23 20:06:30 +00:00
2018-04-29 12:47:24 +00:00
page . getAlbumsSidebar ( )
2018-09-07 15:22:17 +00:00
2018-12-18 17:01:28 +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 . logout = function ( ) {
2019-01-03 04:49:56 +00:00
localStorage . removeItem ( lsKeys . token )
2018-01-24 15:31:23 +00:00
location . reload ( '.' )
2018-01-23 20:06:30 +00:00
}
2018-09-04 15:49:37 +00:00
page . getItemID = function ( element ) {
// This expects the item's parent to have the item's ID
2018-10-09 19:52:41 +00:00
let parent = element . parentNode
2018-09-04 15:49:37 +00:00
// If the element is part of a set of controls, use the container's parent instead
2018-12-18 17:01:28 +00:00
if ( element . parentNode . classList . contains ( 'controls' ) ) parent = parent . parentNode
2018-09-04 15:49:37 +00:00
return parseInt ( parent . dataset . id )
}
page . domClick = function ( event ) {
2019-06-03 19:40:24 +00:00
// We are processing clicks this way to avoid using "onclick" attribute
// Apparently we will need to use "unsafe-inline" for "script-src" directive
2019-06-04 00:57:37 +00:00
// of Content Security Policy (CSP), if we want to use "onclick" attribute
2019-06-03 19:40:24 +00:00
// Though I think that only applies to some browsers (?)
// Of course it wouldn't have mattered if we didn't use CSP to begin with
2019-08-26 22:00:57 +00:00
// Anyway, I personally would rather not use "onclick" attribute
2018-10-09 19:52:41 +00:00
let element = event . target
2018-12-18 17:01:28 +00:00
if ( ! element ) return
2018-09-04 15:49:37 +00:00
2019-09-08 01:56:29 +00:00
// Delegate click events to their A or BUTTON parents
if ( [ 'I' ] . includes ( element . tagName ) && [ 'SPAN' ] . includes ( element . parentNode . tagName ) )
element = element . parentNode
if ( [ 'SPAN' ] . includes ( element . tagName ) && [ 'A' , 'BUTTON' ] . includes ( element . parentNode . tagName ) )
element = element . parentNode
2018-09-04 15:49:37 +00:00
// Skip elements that have no action data
2018-12-18 17:01:28 +00:00
if ( ! element . dataset || ! element . dataset . action ) return
2018-09-04 15:49:37 +00:00
2019-01-01 19:39:08 +00:00
// Skip disabled elements
if ( element . hasAttribute ( 'disabled' ) ) return
2018-09-04 15:49:37 +00:00
event . stopPropagation ( ) // maybe necessary
2018-10-09 19:52:41 +00:00
const id = page . getItemID ( element )
const action = element . dataset . action
2018-09-04 15:49:37 +00:00
switch ( action ) {
2018-09-07 15:02:04 +00:00
case 'view-list' :
2018-10-09 19:52:41 +00:00
return page . setUploadsView ( 'list' , element )
2018-09-07 15:02:04 +00:00
case 'view-thumbs' :
2018-10-09 19:52:41 +00:00
return page . setUploadsView ( 'thumbs' , element )
2018-09-07 15:02:04 +00:00
case 'clear-selection' :
return page . clearSelection ( )
case 'add-selected-files-to-album' :
return page . addSelectedFilesToAlbum ( )
case 'bulk-delete' :
return page . deleteSelectedFiles ( )
2018-10-09 19:52:41 +00:00
case 'select' :
return page . select ( element , event )
2018-09-07 15:02:04 +00:00
case 'add-to-album' :
return page . addSingleFileToAlbum ( id )
case 'delete-file' :
return page . deleteFile ( id )
2018-10-09 19:52:41 +00:00
case 'select-all' :
return page . selectAll ( element )
2018-09-07 15:02:04 +00:00
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 )
2018-10-09 19:52:41 +00:00
case 'edit-user' :
return page . editUser ( id )
2019-01-01 19:39:08 +00:00
case 'disable-user' :
return page . disableUser ( id )
2019-06-17 19:34:15 +00:00
case 'filters-help' :
return page . filtersHelp ( element )
case 'filter-uploads' :
return page . filterUploads ( element )
2019-01-03 04:49:56 +00:00
case 'view-user-uploads' :
return page . viewUserUploads ( id )
2019-08-26 22:23:54 +00:00
case 'page-ellipsis' :
return page . focusJumpToPage ( )
2019-01-03 04:49:56 +00:00
case 'page-prev' :
case 'page-next' :
case 'page-goto' :
case 'jump-to-page' :
return page . switchPage ( action , element )
2018-09-04 15:49:37 +00:00
}
}
2018-07-14 03:42:18 +00:00
page . isLoading = function ( element , state ) {
2018-12-18 17:01:28 +00:00
if ( ! element ) return
if ( state ) return element . classList . add ( 'is-loading' )
2018-05-01 14:41:25 +00:00
element . classList . remove ( 'is-loading' )
2018-03-28 17:40:50 +00:00
}
2019-09-01 19:23:16 +00:00
page . fadeAndScroll = function ( content ) {
2018-12-04 11:58:53 +00:00
if ( page . fadingIn ) {
clearTimeout ( page . fadingIn )
page . dom . classList . remove ( 'fade-in' )
}
page . dom . classList . add ( 'fade-in' )
page . fadingIn = setTimeout ( function ( ) {
page . dom . classList . remove ( 'fade-in' )
} , 500 )
2019-09-01 19:23:16 +00:00
page . dom . scrollIntoView ( true )
2018-12-04 11:58:53 +00:00
}
2019-01-03 04:49:56 +00:00
page . switchPage = function ( action , element ) {
2019-09-01 19:23:16 +00:00
const views = { }
2019-01-03 04:49:56 +00:00
let func = null
2018-01-23 20:06:30 +00:00
2019-01-03 04:49:56 +00:00
if ( page . currentView === 'users' ) {
func = page . getUsers
} else {
func = page . getUploads
views . album = page . views [ page . currentView ] . album
views . all = page . views [ page . currentView ] . all
2019-06-17 19:34:15 +00:00
views . filters = page . views [ page . currentView ] . filters
2019-01-03 04:49:56 +00:00
}
2018-01-23 20:06:30 +00:00
2019-01-03 04:49:56 +00:00
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 )
case 'page-goto' :
views . pageNum = parseInt ( element . dataset . goto )
return func ( views , element )
2019-08-20 02:16:34 +00:00
case 'jump-to-page' : {
2019-09-08 01:56:29 +00:00
const jumpToPage = document . querySelector ( '#jumpToPage' )
if ( ! jumpToPage . checkValidity ( ) ) return
const parsed = parseInt ( jumpToPage . value )
views . pageNum = isNaN ( parsed ) ? 0 : ( parsed - 1 )
2019-01-03 04:49:56 +00:00
if ( views . pageNum < 0 ) views . pageNum = 0
return func ( views , element )
2019-08-20 02:16:34 +00:00
}
2019-01-03 04:49:56 +00:00
}
}
2019-08-26 22:23:54 +00:00
page . focusJumpToPage = function ( ) {
const element = document . querySelector ( '#jumpToPage' )
if ( ! element ) return
element . focus ( )
element . select ( )
}
2019-09-08 01:56:29 +00:00
page . getUploads = function ( { pageNum , album , all , filters , autoPage } = { } , element ) {
2019-01-03 04:49:56 +00:00
if ( element ) page . isLoading ( element , true )
2019-06-17 19:34:15 +00:00
if ( ( all || filters ) && ! page . permissions . moderator )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , 'You can not do this!' , 'error' )
2018-05-06 14:14:57 +00:00
2019-01-03 04:49:56 +00:00
if ( typeof pageNum !== 'number' || pageNum < 0 )
pageNum = 0
let url = ` api/uploads/ ${ pageNum } `
if ( typeof album === 'string' )
url = ` api/album/ ${ album } / ${ pageNum } `
const headers = { }
if ( all ) headers . all = '1'
2019-06-17 19:34:15 +00:00
if ( filters ) headers . filters = filters
2019-01-03 04:49:56 +00:00
axios . get ( url , { headers } ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
2019-06-04 00:57:37 +00:00
if ( element ) page . isLoading ( element , false )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , response . data . description , 'error' )
2018-09-04 15:49:37 +00:00
}
2019-06-04 00:57:37 +00:00
const files = response . data . files
2019-06-18 18:48:30 +00:00
if ( pageNum && ( files . length === 0 ) ) {
2018-12-18 17:01:28 +00:00
if ( element ) page . isLoading ( element , false )
2019-09-08 01:56:29 +00:00
if ( autoPage )
return page . getUploads ( {
pageNum : Math . ceil ( response . data . count / 25 ) - 1 ,
album ,
all ,
filters
} , element )
else
return swal ( 'An error occurred!' , ` There are no more uploads to populate page ${ pageNum + 1 } . ` , 'error' )
2018-10-09 19:52:41 +00:00
}
2019-01-03 04:49:56 +00:00
page . currentView = all ? 'uploadsAll' : 'uploads'
2018-10-09 19:52:41 +00:00
page . cache . uploads = { }
2019-06-04 00:57:37 +00:00
const albums = response . data . albums
const users = response . data . users
const basedomain = response . data . basedomain
2019-01-01 19:39:08 +00:00
const pagination = page . paginate ( response . data . count , 25 , pageNum )
2018-10-09 19:52:41 +00:00
2019-06-17 19:34:15 +00:00
let filter = '<div class="column is-hidden-mobile"></div>'
2019-01-03 04:49:56 +00:00
if ( all )
filter = `
2019-06-17 19:34:15 +00:00
< div class = "column" >
2019-08-26 22:00:57 +00:00
< form class = "prevent-default" >
< div class = "field has-addons" >
< div class = "control is-expanded" >
< input id = "filters" class = "input is-small" type = "text" placeholder = "Filters" value = "${filters || ''}" >
< / d i v >
< div class = "control" >
< button type = "button" class = "button is-small is-breeze" title = "Help?" data - action = "filters-help" >
< span class = "icon" >
< i class = "icon-help-circled" > < / i >
< / s p a n >
< / b u t t o n >
< / d i v >
< div class = "control" >
< button type = "submit" class = "button is-small is-breeze" title = "Filter uploads" data - action = "filter-uploads" >
< span class = "icon" >
< i class = "icon-filter" > < / i >
< / s p a n >
< / b u t t o n >
< / d i v >
2019-01-03 04:49:56 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< / f o r m >
2019-01-03 04:49:56 +00:00
< / d i v >
`
const extraControls = `
< div class = "columns" style = "margin-top: 10px" >
$ { filter }
< div class = "column is-one-quarter" >
2019-08-26 22:00:57 +00:00
< form class = "prevent-default" >
< div class = "field has-addons" >
< div class = "control is-expanded" >
2019-09-08 01:56:29 +00:00
< input id = "jumpToPage" class = "input is-small" type = "number" value = "${pageNum + 1}" >
2019-08-26 22:00:57 +00:00
< / d i v >
< div class = "control" >
< button type = "submit" class = "button is-small is-breeze" title = "Jump to page" data - action = "jump-to-page" >
< span class = "icon" >
< i class = "icon-paper-plane-empty" > < / i >
< / s p a n >
< / b u t t o n >
< / d i v >
2019-01-03 04:49:56 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< / f o r m >
2019-01-03 04:49:56 +00:00
< / d i v >
< / d i v >
`
2018-10-09 19:52:41 +00:00
const controls = `
< div class = "columns" >
< div class = "column is-hidden-mobile" > < / d i v >
< div class = "column" style = "text-align: center" >
< a class = "button is-small is-danger" title = "List view" data - action = "view-list" >
< span class = "icon" >
< i class = "icon-th-list" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-danger" title = "Thumbs view" data - action = "view-thumbs" >
< span class = "icon" >
< i class = "icon-th-large" > < / i >
< / s p a n >
< / a >
< / d i v >
< div class = "column" style = "text-align: right" >
< a class = "button is-small is-info" title = "Clear selection" data - action = "clear-selection" >
< span class = "icon" >
< i class = "icon-cancel" > < / i >
< / s p a n >
< / a >
$ { all ? '' : `
< a class = "button is-small is-warning" title = "Add selected uploads to album" data - action = "add-selected-files-to-album" >
< span class = "icon" >
< i class = "icon-plus" > < / i >
< / s p a n >
< / a > ` }
< a class = "button is-small is-danger" title = "Bulk delete" data - action = "bulk-delete" >
< span class = "icon" >
< i class = "icon-trash" > < / i >
< / s p a n >
< span > Bulk delete < / s p a n >
< / a >
< / d i v >
< / d i v >
`
2019-06-04 00:57:37 +00:00
// Set to true to tick "all files" checkbox in list view
2018-10-09 19:52:41 +00:00
let allSelected = true
2019-06-04 00:57:37 +00:00
2019-09-08 01:56:29 +00:00
const hasExpiryDateColumn = files . some ( file => file . expirydate !== undefined )
2019-06-04 00:57:37 +00:00
for ( let i = 0 ; i < files . length ; i ++ ) {
// Build full URLs
files [ i ] . file = ` ${ basedomain } / ${ files [ i ] . name } `
2019-09-08 01:56:29 +00:00
if ( files [ i ] . thumb )
files [ i ] . thumb = ` ${ basedomain } / ${ files [ i ] . thumb } `
2019-06-04 00:57:37 +00:00
// Cache bare minimum data for thumbnails viewer
page . cache . uploads [ files [ i ] . id ] = {
name : files [ i ] . name ,
thumb : files [ i ] . thumb ,
original : files [ i ] . file
}
2019-09-08 01:56:29 +00:00
2019-06-04 00:57:37 +00:00
// Prettify
files [ i ] . prettyBytes = page . getPrettyBytes ( parseInt ( files [ i ] . size ) )
files [ i ] . prettyDate = page . getPrettyDate ( new Date ( files [ i ] . timestamp * 1000 ) )
2019-09-08 01:56:29 +00:00
if ( hasExpiryDateColumn )
files [ i ] . prettyExpiryDate = files [ i ] . expirydate
? page . getPrettyDate ( new Date ( files [ i ] . expirydate * 1000 ) )
: '-'
2019-06-04 00:57:37 +00:00
// Update selected status
files [ i ] . selected = page . selected [ page . currentView ] . includes ( files [ i ] . id )
if ( allSelected && ! files [ i ] . selected ) allSelected = false
2019-09-08 01:56:29 +00:00
2019-06-04 00:57:37 +00:00
// Appendix (display album or user)
2019-09-08 01:56:29 +00:00
if ( all )
files [ i ] . appendix = files [ i ] . userid
? users [ files [ i ] . userid ] || ''
: ''
else
files [ i ] . appendix = files [ i ] . albumid
? albums [ files [ i ] . albumid ] || ''
: ''
2019-06-04 00:57:37 +00:00
}
2019-01-03 04:49:56 +00:00
if ( page . views [ page . currentView ] . type === 'thumbs' ) {
2018-10-09 19:52:41 +00:00
page . dom . innerHTML = `
$ { pagination }
2019-01-03 04:49:56 +00:00
$ { extraControls }
2018-10-09 19:52:41 +00:00
$ { controls }
< div id = "table" class = "columns is-multiline is-mobile is-centered" >
< / d i v >
2019-01-01 19:39:08 +00:00
< hr >
2018-10-09 19:52:41 +00:00
$ { pagination }
`
2019-08-20 02:16:34 +00:00
const table = document . querySelector ( '#table' )
2018-10-09 19:52:41 +00:00
2019-06-04 00:57:37 +00:00
for ( let i = 0 ; i < files . length ; i ++ ) {
const upload = files [ i ]
2018-10-09 19:52:41 +00:00
const div = document . createElement ( 'div' )
div . className = 'image-container column is-narrow'
div . dataset . id = upload . id
2019-09-08 01:56:29 +00:00
2018-12-18 17:01:28 +00:00
if ( upload . thumb !== undefined )
2018-10-09 19:52:41 +00:00
div . innerHTML = ` <a class="image" href=" ${ upload . file } " target="_blank" rel="noopener"><img alt=" ${ upload . name } " data-src=" ${ upload . thumb } "/></a> `
2018-12-18 17:01:28 +00:00
else
2018-10-09 19:52:41 +00:00
div . innerHTML = ` <a class="image" href=" ${ upload . file } " target="_blank" rel="noopener"><h1 class="title"> ${ upload . extname || 'N/A' } </h1></a> `
div . innerHTML += `
2019-06-04 00:57:37 +00:00
< input type = "checkbox" class = "checkbox" title = "Select this file" data - action = "select" $ { upload . selected ? ' checked' : '' } >
2018-10-09 19:52:41 +00:00
< div class = "controls" >
2018-10-18 13:26:40 +00:00
< a class = "button is-small is-primary" title = "View thumbnail" data - action = "display-thumbnail" $ { upload . thumb ? '' : ' disabled' } >
< span class = "icon" >
< i class = "icon-picture-1" > < / i >
< / s p a n >
< / a >
2018-10-09 19:52:41 +00:00
< a class = "button is-small is-info clipboard-js" title = "Copy link to clipboard" data - clipboard - text = "${upload.file}" >
< span class = "icon" >
< i class = "icon-clipboard-1" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-warning" title = "Add to album" data - action = "add-to-album" >
< span class = "icon" >
< i class = "icon-plus" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-danger" title = "Delete file" data - action = "delete-file" >
< span class = "icon" >
< i class = "icon-trash" > < / i >
< / s p a n >
< / a >
< / d i v >
< div class = "details" >
< p > < span class = "name" title = "${upload.file}" > $ { upload . name } < / s p a n > < / p >
2019-06-04 00:57:37 +00:00
< p > $ { upload . appendix ? ` <span> ${ upload . appendix } </span> – ` : '' } $ { upload . prettyBytes } < / p >
2018-10-09 19:52:41 +00:00
< / d i v >
`
table . appendChild ( div )
2019-01-03 04:49:56 +00:00
page . checkboxes [ page . currentView ] = Array . from ( table . querySelectorAll ( '.checkbox[data-action="select"]' ) )
2018-10-09 19:52:41 +00:00
page . lazyLoad . update ( )
2018-07-14 03:42:18 +00:00
}
2018-10-09 19:52:41 +00:00
} else {
page . dom . innerHTML = `
$ { pagination }
2019-01-03 04:49:56 +00:00
$ { extraControls }
2018-10-09 19:52:41 +00:00
$ { controls }
< div class = "table-container" >
< table class = "table is-narrow is-fullwidth is-hoverable" >
< thead >
< tr >
< th > < input id = "selectAll" class = "checkbox" type = "checkbox" title = "Select all uploads" data - action = "select-all" > < / t h >
2019-09-08 01:56:29 +00:00
< th style = "width: 20%" > File < / t h >
2019-06-04 00:57:37 +00:00
< th > $ { all ? 'User' : 'Album' } < / t h >
2018-10-09 19:52:41 +00:00
< th > Size < / t h >
2019-06-04 00:57:37 +00:00
$ { all ? '<th>IP</th>' : '' }
2018-10-09 19:52:41 +00:00
< th > Date < / t h >
2019-09-08 01:56:29 +00:00
$ { hasExpiryDateColumn ? '<th>Expiry date</th>' : '' }
2018-10-09 19:52:41 +00:00
< th > < / t h >
< / t r >
< / t h e a d >
< tbody id = "table" >
< / t b o d y >
< / t a b l e >
< / d i v >
< hr >
$ { pagination }
`
2019-08-20 02:16:34 +00:00
const table = document . querySelector ( '#table' )
2018-10-09 19:52:41 +00:00
2019-06-04 00:57:37 +00:00
for ( let i = 0 ; i < files . length ; i ++ ) {
const upload = files [ i ]
2018-10-09 19:52:41 +00:00
const tr = document . createElement ( 'tr' )
tr . dataset . id = upload . id
tr . innerHTML = `
2019-06-04 00:57:37 +00:00
< td class = "controls" > < input type = "checkbox" class = "checkbox" title = "Select this file" data - action = "select" $ { upload . selected ? ' checked' : '' } > < / t d >
2018-10-09 19:52:41 +00:00
< th > < a href = "${upload.file}" target = "_blank" rel = "noopener" title = "${upload.file}" > $ { upload . name } < / a > < / t h >
2019-06-04 00:57:37 +00:00
< th > $ { upload . appendix } < / t h >
2018-10-09 19:52:41 +00:00
< td > $ { upload . prettyBytes } < / t d >
2019-06-04 00:57:37 +00:00
$ { all ? ` <td> ${ upload . ip || '' } </td> ` : '' }
2018-10-09 19:52:41 +00:00
< td > $ { upload . prettyDate } < / t d >
2019-09-08 01:56:29 +00:00
$ { hasExpiryDateColumn ? ` <td> ${ upload . prettyExpiryDate } </td> ` : '' }
2018-10-09 19:52:41 +00:00
< td class = "controls" style = "text-align: right" >
< a class = "button is-small is-primary" title = "View thumbnail" data - action = "display-thumbnail" $ { upload . thumb ? '' : ' disabled' } >
< span class = "icon" >
< i class = "icon-picture-1" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-info clipboard-js" title = "Copy link to clipboard" data - clipboard - text = "${upload.file}" >
< span class = "icon" >
< i class = "icon-clipboard-1" > < / i >
< / s p a n >
< / a >
$ { all ? '' : `
< a class = "button is-small is-warning" title = "Add to album" data - action = "add-to-album" >
< span class = "icon" >
< i class = "icon-plus" > < / i >
< / s p a n >
< / a > ` }
< a class = "button is-small is-danger" title = "Delete file" data - action = "delete-file" >
< span class = "icon" >
< i class = "icon-trash" > < / i >
< / s p a n >
< / a >
< / t d >
`
table . appendChild ( tr )
2019-01-03 04:49:56 +00:00
page . checkboxes [ page . currentView ] = Array . from ( table . querySelectorAll ( '.checkbox[data-action="select"]' ) )
2018-07-14 03:42:18 +00:00
}
2018-10-09 19:52:41 +00:00
}
2019-09-08 01:56:29 +00:00
page . fadeAndScroll ( )
2018-04-28 23:44:25 +00:00
2019-06-04 00:57:37 +00:00
if ( allSelected && files . length ) {
2019-08-20 02:16:34 +00:00
const selectAll = document . querySelector ( '#selectAll' )
2018-12-18 17:01:28 +00:00
if ( selectAll ) selectAll . checked = true
2018-10-09 19:52:41 +00:00
}
2019-01-03 04:49:56 +00:00
if ( page . currentView === 'uploads' ) page . views . uploads . album = album
2019-06-17 19:34:15 +00:00
if ( page . currentView === 'uploadsAll' ) page . views . uploadsAll . filters = filters
2019-06-04 00:57:37 +00:00
page . views [ page . currentView ] . pageNum = files . length ? pageNum : 0
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2018-12-18 17:01:28 +00:00
if ( element ) page . isLoading ( element , false )
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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-10-09 19:52:41 +00:00
page . setUploadsView = function ( view , element ) {
2019-01-03 04:49:56 +00:00
localStorage [ lsKeys . viewType [ page . currentView ] ] = view
page . views [ page . currentView ] . type = view
page . getUploads ( page . views [ page . currentView ] , element )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . displayThumbnail = function ( id ) {
2018-10-09 19:52:41 +00:00
const file = page . cache . uploads [ id ]
2018-12-18 17:01:28 +00:00
if ( ! file . thumb ) return
2018-10-18 13:26:40 +00:00
const div = document . createElement ( 'div' )
div . innerHTML = `
< div class = "field has-text-centered" >
< label class = "label" > $ { file . name } < / l a b e l >
2019-01-09 05:04:21 +00:00
< div class = "controls swal-display-thumb-container" >
2018-10-18 13:26:40 +00:00
< img id = "swalThumb" src = "${file.thumb}" >
< / d i v >
< / d i v >
`
if ( file . original ) {
div . innerHTML += `
< div class = "field has-text-centered" >
< div class = "controls" >
< a id = "swalOriginal" type = "button" class = "button is-breeze" data - original = "${file.original}" > Load original < / a >
< / d i v >
< / d i v >
`
div . querySelector ( '#swalOriginal' ) . addEventListener ( 'click' , function ( ) {
const button = this
const original = button . dataset . original
button . classList . add ( 'is-loading' )
const thumb = div . querySelector ( '#swalThumb' )
const exec = /.[\w]+(\?|$)/ . exec ( original )
const isimage = exec && exec [ 0 ] && page . imageExtensions . includes ( exec [ 0 ] . toLowerCase ( ) )
if ( isimage ) {
thumb . src = file . original
2018-10-19 15:10:30 +00:00
thumb . onload = function ( ) {
button . style . display = 'none'
document . body . querySelector ( '.swal-overlay .swal-modal:not(.is-expanded)' ) . classList . add ( 'is-expanded' )
}
thumb . onerror = function ( ) {
button . className = 'button is-danger'
button . innerHTML = 'Unable to load original'
}
2018-10-18 13:26:40 +00:00
} else {
thumb . style . display = 'none'
const video = document . createElement ( 'video' )
video . id = 'swalVideo'
video . controls = true
video . src = file . original
thumb . insertAdjacentElement ( 'afterend' , video )
2018-10-19 15:10:30 +00:00
2018-10-18 13:26:40 +00:00
button . style . display = 'none'
2018-10-19 15:10:30 +00:00
document . body . querySelector ( '.swal-overlay .swal-modal:not(.is-expanded)' ) . classList . add ( 'is-expanded' )
2018-10-18 13:26:40 +00:00
}
} )
}
2018-07-14 03:42:18 +00:00
return swal ( {
2018-10-18 13:26:40 +00:00
content : div ,
buttons : false
} ) . then ( function ( ) {
const video = div . querySelector ( '#swalVideo' )
2018-12-18 17:01:28 +00:00
if ( video ) video . remove ( )
2018-10-19 14:57:15 +00:00
// Restore modal size
document . body . querySelector ( '.swal-overlay .swal-modal.is-expanded' ) . classList . remove ( 'is-expanded' )
2018-05-01 14:41:25 +00:00
} )
2018-03-29 23:22:08 +00:00
}
2018-10-09 19:52:41 +00:00
page . selectAll = function ( element ) {
2019-01-05 22:53:08 +00:00
const checkboxes = page . checkboxes [ page . currentView ]
const selected = page . selected [ page . currentView ]
2018-04-03 15:59:39 +00:00
2018-10-09 19:52:41 +00:00
for ( let i = 0 ; i < checkboxes . length ; i ++ ) {
const id = page . getItemID ( checkboxes [ i ] )
2018-12-18 17:01:28 +00:00
if ( isNaN ( id ) ) continue
2018-07-14 04:37:36 +00:00
if ( checkboxes [ i ] . checked !== element . checked ) {
checkboxes [ i ] . checked = element . checked
2018-12-18 17:01:28 +00:00
if ( checkboxes [ i ] . checked )
2018-10-09 19:52:41 +00:00
selected . push ( id )
2018-12-18 17:01:28 +00:00
else
2018-10-09 19:52:41 +00:00
selected . splice ( selected . indexOf ( id ) , 1 )
2018-03-29 23:22:08 +00:00
}
}
2018-04-03 15:59:39 +00:00
2019-01-05 22:53:08 +00:00
localStorage [ lsKeys . selected [ page . currentView ] ] = JSON . stringify ( selected )
page . selected [ page . currentView ] = selected
2018-10-09 19:52:41 +00:00
element . title = element . checked ? 'Unselect all uploads' : 'Select all uploads'
2018-03-29 23:22:08 +00:00
}
2018-07-14 03:42:18 +00:00
page . selectInBetween = function ( element , lastElement ) {
2018-12-18 17:01:28 +00:00
if ( ! element || ! lastElement ) return
if ( element === lastElement ) return
2018-04-04 18:23:45 +00:00
2019-01-05 22:53:08 +00:00
const checkboxes = page . checkboxes [ page . currentView ]
2018-12-18 17:01:28 +00:00
if ( ! checkboxes || ! checkboxes . length ) return
2018-04-04 18:23:45 +00:00
2018-10-09 19:52:41 +00:00
const thisIndex = checkboxes . indexOf ( element )
const lastIndex = checkboxes . indexOf ( lastElement )
const distance = thisIndex - lastIndex
2018-12-18 17:01:28 +00:00
if ( distance >= - 1 && distance <= 1 ) return
2018-04-04 18:23:45 +00:00
2018-12-18 17:01:28 +00:00
for ( let i = 0 ; i < checkboxes . length ; i ++ )
2018-04-04 18:23:45 +00:00
if ( ( thisIndex > lastIndex && i > lastIndex && i < thisIndex ) ||
( thisIndex < lastIndex && i > thisIndex && i < lastIndex ) ) {
2018-10-09 19:52:41 +00:00
checkboxes [ i ] . checked = true
2019-01-05 22:53:08 +00:00
page . selected [ page . currentView ] . push ( page . getItemID ( checkboxes [ i ] ) )
2018-04-04 18:23:45 +00:00
}
2019-01-05 22:53:08 +00:00
localStorage [ lsKeys . selected [ page . currentView ] ] = JSON . stringify ( page . selected [ page . currentView ] )
page . checkboxes [ page . currentView ] = checkboxes
2018-04-04 18:23:45 +00:00
}
2018-10-09 19:52:41 +00:00
page . select = function ( element , event ) {
2019-01-05 22:53:08 +00:00
const lastSelected = page . lastSelected [ page . currentView ]
2018-12-18 17:01:28 +00:00
if ( event . shiftKey && lastSelected )
2018-10-09 19:52:41 +00:00
page . selectInBetween ( element , lastSelected )
2018-12-18 17:01:28 +00:00
else
2019-01-05 22:53:08 +00:00
page . lastSelected [ page . currentView ] = element
2018-04-04 18:23:45 +00:00
2018-10-09 19:52:41 +00:00
const id = page . getItemID ( element )
2018-12-18 17:01:28 +00:00
if ( isNaN ( id ) ) return
2018-04-03 15:59:39 +00:00
2019-01-05 22:53:08 +00:00
const selected = page . selected [ page . currentView ]
2018-12-18 17:01:28 +00:00
if ( ! selected . includes ( id ) && element . checked )
2018-10-09 19:52:41 +00:00
selected . push ( id )
2018-12-18 17:01:28 +00:00
else if ( selected . includes ( id ) && ! element . checked )
2018-10-09 19:52:41 +00:00
selected . splice ( selected . indexOf ( id ) , 1 )
2018-04-03 15:59:39 +00:00
2019-01-05 22:53:08 +00:00
localStorage [ lsKeys . selected [ page . currentView ] ] = JSON . stringify ( selected )
page . selected [ page . currentView ] = selected
2018-03-29 23:22:08 +00:00
}
2018-07-14 03:42:18 +00:00
page . clearSelection = function ( ) {
2019-01-05 22:53:08 +00:00
const selected = page . selected [ page . currentView ]
2019-01-03 04:49:56 +00:00
const type = page . currentView === 'users' ? 'users' : 'uploads'
2018-10-09 19:52:41 +00:00
const count = selected . length
2018-12-18 17:01:28 +00:00
if ( ! count )
2019-01-03 04:49:56 +00:00
return swal ( 'An error occurred!' , ` You have not selected any ${ type } . ` , 'error' )
2018-04-03 15:59:39 +00:00
2019-01-03 04:49:56 +00:00
const suffix = count === 1 ? type . substring ( 0 , type . length - 1 ) : type
2018-07-14 03:42:18 +00:00
return swal ( {
2018-04-03 15:59:39 +00:00
title : 'Are you sure?' ,
2018-10-09 19:52:41 +00:00
text : ` You are going to unselect ${ count } ${ suffix } . ` ,
2018-04-03 15:59:39 +00:00
buttons : true
2018-10-09 19:52:41 +00:00
} ) . then ( function ( proceed ) {
2018-12-18 17:01:28 +00:00
if ( ! proceed ) return
2018-04-03 15:59:39 +00:00
2019-01-05 22:53:08 +00:00
const checkboxes = page . checkboxes [ page . currentView ]
2018-12-18 17:01:28 +00:00
for ( let i = 0 ; i < checkboxes . length ; i ++ )
if ( checkboxes [ i ] . checked )
2018-10-09 19:52:41 +00:00
checkboxes [ i ] . checked = false
2018-04-03 15:59:39 +00:00
2019-01-05 22:53:08 +00:00
page . selected [ page . currentView ] = [ ]
2019-09-08 01:56:29 +00:00
delete localStorage [ lsKeys . selected [ page . currentView ] ]
2018-04-03 15:59:39 +00:00
2019-08-20 02:16:34 +00:00
const selectAll = document . querySelector ( '#selectAll' )
2018-12-18 17:01:28 +00:00
if ( selectAll ) selectAll . checked = false
2018-04-03 15:59:39 +00:00
2018-10-09 19:52:41 +00:00
return swal ( 'Cleared selection!' , ` Unselected ${ count } ${ suffix } . ` , 'success' )
} )
2018-04-03 15:59:39 +00:00
}
2019-06-17 19:34:15 +00:00
page . filtersHelp = function ( element ) {
const content = document . createElement ( 'div' )
content . style = 'text-align: left'
content . innerHTML = `
This supports 3 filter keys , namely < b > user < / b > ( u s e r n a m e ) , < b > i p < / b > a n d < b > n a m e < / b > ( f i l e n a m e ) .
Each key can be specified more than once .
Backlashes should be used if the usernames have spaces .
There are also 2 additional flags , namely < b > - user < / b > a n d < b > - i p < / b > , w h i c h w i l l m a t c h u p l o a d s b y n o n - r e g i s t e r e d u s e r s a n d h a v e n o I P s r e s p e c t i v e l y .
How does it work ?
First , it will filter uploads matching ANY of the supplied < b > user < / b > o r < b > i p < / b > k e y s .
Then , it will refine the matches using the supplied < b > name < / b > k e y s .
Examples :
Uploads from user with username "demo" :
2019-09-08 01:56:29 +00:00
< code > user : demo < / c o d e >
2019-06-17 19:34:15 +00:00
Uploads from users with username either "John Doe" OR "demo" :
2019-09-08 01:56:29 +00:00
< code > user : John \ \ Doe user : demo < / c o d e >
2019-06-17 19:34:15 +00:00
Uploads from IP "127.0.0.1" AND which file names match "*.rar" OR "*.zip" :
2019-09-08 01:56:29 +00:00
< code > ip : 127.0 . 0.1 name : * . rar name : * . zip < / c o d e >
2019-06-17 19:34:15 +00:00
Uploads from user with username "test" OR from non - registered users :
2019-09-08 01:56:29 +00:00
< code > user : test - user < / c o d e >
2019-06-17 19:34:15 +00:00
` .trim().replace(/^ {6}/gm, '').replace(/ \n /g, '<br>')
swal ( { content } )
}
page . filterUploads = function ( element ) {
2019-08-20 02:16:34 +00:00
const filters = document . querySelector ( '#filters' ) . value
2019-06-17 19:34:15 +00:00
page . getUploads ( { all : true , filters } , element )
2019-01-03 04:49:56 +00:00
}
page . viewUserUploads = function ( id ) {
const user = page . cache . users [ id ]
if ( ! user ) return
2019-08-20 02:16:34 +00:00
page . setActiveMenu ( document . querySelector ( '#itemManageUploads' ) )
2019-06-17 19:34:15 +00:00
page . getUploads ( { all : true , filters : ` user: ${ user . username . replace ( / /g , '\\ ' ) } ` } )
2019-01-03 04:49:56 +00:00
}
2018-07-14 03:42:18 +00:00
page . deleteFile = function ( id ) {
2018-10-09 19:52:41 +00:00
// TODO: Share function with bulk delete, just like 'add selected uploads to album' and 'add single file to album'
2018-07-14 03:42:18 +00:00
swal ( {
2018-01-23 20:06:30 +00:00
title : 'Are you sure?' ,
2018-03-24 19:47:41 +00:00
text : 'You won\'t be able to recover the file!' ,
2018-03-19 16:51:39 +00:00
icon : 'warning' ,
dangerMode : true ,
buttons : {
cancel : true ,
confirm : {
text : 'Yes, delete it!' ,
closeModal : false
}
}
2018-10-09 19:52:41 +00:00
} ) . then ( function ( proceed ) {
2018-12-18 17:01:28 +00:00
if ( ! proceed ) return
2018-10-09 19:52:41 +00:00
axios . post ( 'api/upload/delete' , { id } ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( ! response ) return
2018-10-09 19:52:41 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
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' )
2019-09-08 01:56:29 +00:00
const views = Object . assign ( { } , page . views [ page . currentView ] )
views . autoPage = true
page . getUploads ( views )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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-10-09 19:52:41 +00:00
} )
2018-03-29 23:22:08 +00:00
}
2018-07-14 03:42:18 +00:00
page . deleteSelectedFiles = function ( ) {
2019-01-03 04:49:56 +00:00
const count = page . selected [ page . currentView ] . length
2018-12-18 17:01:28 +00:00
if ( ! count )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , 'You have not selected any uploads.' , 'error' )
2018-03-29 23:22:08 +00:00
2019-01-03 04:49:56 +00:00
const suffix = ` upload ${ count === 1 ? '' : 's' } `
let text = ` You won't be able to recover ${ count } ${ suffix } ! `
if ( page . currentView === 'uploadsAll' )
text += '\nBe aware, you may be nuking uploads by other users!'
2018-07-14 03:42:18 +00:00
swal ( {
2018-03-29 23:22:08 +00:00
title : 'Are you sure?' ,
2019-01-03 04:49:56 +00:00
text ,
2018-03-29 23:22:08 +00:00
icon : 'warning' ,
dangerMode : true ,
buttons : {
cancel : true ,
confirm : {
2018-10-09 19:52:41 +00:00
text : ` Yes, nuke the ${ suffix } ! ` ,
2018-03-29 23:22:08 +00:00
closeModal : false
}
}
2018-10-09 19:52:41 +00:00
} ) . then ( function ( proceed ) {
2018-12-18 17:01:28 +00:00
if ( ! proceed ) return
2018-03-31 14:26:53 +00:00
2018-10-09 19:52:41 +00:00
axios . post ( 'api/upload/bulkdelete' , {
field : 'id' ,
2019-01-03 04:49:56 +00:00
values : page . selected [ page . currentView ]
2018-10-09 19:52:41 +00:00
} ) . then ( function ( bulkdelete ) {
2018-12-18 17:01:28 +00:00
if ( ! bulkdelete ) return
2018-10-09 19:52:41 +00:00
2018-12-18 17:01:28 +00:00
if ( bulkdelete . data . success === false )
2018-10-09 19:52:41 +00:00
if ( bulkdelete . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , bulkdelete . data . description , 'error' )
}
2019-09-08 01:56:29 +00:00
if ( Array . isArray ( bulkdelete . data . failed ) && bulkdelete . data . failed . length ) {
2019-01-03 04:49:56 +00:00
page . selected [ page . currentView ] = page . selected [ page . currentView ] . filter ( function ( id ) {
2018-10-09 19:52:41 +00:00
return bulkdelete . data . failed . includes ( id )
2018-07-14 03:42:18 +00:00
} )
2019-09-08 01:56:29 +00:00
localStorage [ lsKeys . selected [ page . currentView ] ] = JSON . stringify ( page . selected [ page . currentView ] )
swal ( 'An error ocurrred!' , ` From ${ count } ${ suffix } , unable to delete ${ bulkdelete . data . failed . length } of them. ` , 'error' )
2018-12-18 17:41:42 +00:00
} else {
2019-01-03 04:49:56 +00:00
page . selected [ page . currentView ] = [ ]
2019-09-08 01:56:29 +00:00
delete localStorage [ lsKeys . selected [ page . currentView ] ]
swal ( 'Deleted!' , ` ${ count } ${ suffix } ${ count === 1 ? 'has' : 'have' } been deleted. ` , 'success' )
2018-12-18 17:41:42 +00:00
}
2018-10-09 19:52:41 +00:00
2019-09-08 01:56:29 +00:00
const views = Object . assign ( { } , page . views [ page . currentView ] )
views . autoPage = true
page . getUploads ( views )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
2018-03-29 23:22:08 +00:00
} )
2018-10-09 19:52:41 +00:00
} )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . deleteByNames = function ( ) {
2019-06-03 19:40:24 +00:00
let appendix = ''
if ( page . permissions . moderator )
appendix = '<br>As a staff, you can use this feature to delete uploads by other users.'
2018-10-09 19:52:41 +00:00
page . dom . innerHTML = `
< h2 class = "subtitle" > Delete by names < / h 2 >
< div class = "field" >
< label class = "label" > File names : < / l a b e l >
< div class = "control" >
< textarea id = "names" class = "textarea" > < / t e x t a r e a >
< / d i v >
2019-06-03 19:40:24 +00:00
< p class = "help" > Separate each entry with a new line . $ { appendix } < / p >
2018-10-09 19:52:41 +00:00
< / d i v >
< div class = "field" >
< div class = "control" >
< a class = "button is-danger is-fullwidth" data - action = "delete-file-by-names" >
< span class = "icon" >
< i class = "icon-trash" > < / i >
< / s p a n >
< span > Bulk delete < / s p a n >
< / a >
< / d i v >
< / d i v >
`
2019-09-01 19:23:16 +00:00
page . fadeAndScroll ( )
2018-05-05 19:44:58 +00:00
}
2018-07-14 03:42:18 +00:00
page . deleteFileByNames = function ( ) {
2019-08-20 02:16:34 +00:00
const names = document . querySelector ( '#names' ) . value
2018-07-14 03:42:18 +00:00
. split ( /\r?\n/ )
. filter ( function ( n ) {
return n . trim ( ) . length
} )
2018-10-09 19:52:41 +00:00
const count = names . length
2018-12-18 17:01:28 +00:00
if ( ! count )
2018-05-05 19:44:58 +00:00
return swal ( 'An error occurred!' , 'You have not entered any file names.' , 'error' )
2018-10-09 19:52:41 +00:00
const suffix = ` file ${ count === 1 ? '' : 's' } `
2018-07-14 03:42:18 +00:00
swal ( {
2018-05-05 19:44:58 +00:00
title : 'Are you sure?' ,
2018-10-09 19:52:41 +00:00
text : ` You won't be able to recover ${ count } ${ suffix } ! ` ,
2018-05-05 19:44:58 +00:00
icon : 'warning' ,
dangerMode : true ,
buttons : {
cancel : true ,
confirm : {
2018-10-09 19:52:41 +00:00
text : ` Yes, nuke the ${ suffix } ! ` ,
2018-05-05 19:44:58 +00:00
closeModal : false
}
}
2018-10-09 19:52:41 +00:00
} ) . then ( function ( proceed ) {
2018-12-18 17:01:28 +00:00
if ( ! proceed ) return
2018-05-05 19:44:58 +00:00
2018-10-09 19:52:41 +00:00
axios . post ( 'api/upload/bulkdelete' , {
field : 'name' ,
values : names
} ) . then ( function ( bulkdelete ) {
2018-12-18 17:01:28 +00:00
if ( ! bulkdelete ) return
2018-10-09 19:52:41 +00:00
2018-12-18 17:01:28 +00:00
if ( bulkdelete . data . success === false )
2018-10-09 19:52:41 +00:00
if ( bulkdelete . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , bulkdelete . data . description , 'error' )
}
2019-09-08 01:56:29 +00:00
if ( Array . isArray ( bulkdelete . data . failed ) && bulkdelete . data . failed . length ) {
page . selected [ page . currentView ] = page . selected [ page . currentView ] . filter ( function ( id ) {
return bulkdelete . data . failed . includes ( id )
} )
localStorage [ lsKeys . selected [ page . currentView ] ] = JSON . stringify ( page . selected [ page . currentView ] )
swal ( 'An error ocurrred!' , ` From ${ count } ${ suffix } , unable to delete ${ bulkdelete . data . failed . length } of them. ` , 'error' )
} else {
page . selected [ page . currentView ] = [ ]
delete localStorage [ lsKeys . selected [ page . currentView ] ]
swal ( 'Deleted!' , ` ${ count } ${ suffix } ${ count === 1 ? 'has' : 'have' } been deleted. ` , 'success' )
}
2018-10-09 19:52:41 +00:00
2019-08-20 02:16:34 +00:00
document . querySelector ( '#names' ) . value = bulkdelete . data . failed . join ( '\n' )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
2018-05-05 19:44:58 +00:00
} )
2018-10-09 19:52:41 +00:00
} )
2018-05-05 19:44:58 +00:00
}
2018-07-14 03:42:18 +00:00
page . addSelectedFilesToAlbum = function ( ) {
2019-01-03 04:49:56 +00:00
if ( page . currentView !== 'uploads' )
return
const count = page . selected [ page . currentView ] . length
2018-12-18 17:01:28 +00:00
if ( ! count )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , 'You have not selected any uploads.' , 'error' )
2018-03-30 02:39:53 +00:00
2019-01-03 04:49:56 +00:00
page . addFilesToAlbum ( page . selected [ page . currentView ] , function ( failed ) {
2018-12-18 17:01:28 +00:00
if ( ! failed ) return
if ( failed . length )
2019-01-03 04:49:56 +00:00
page . selected [ page . currentView ] = page . selected [ page . currentView ] . filter ( function ( id ) {
2018-07-14 03:42:18 +00:00
return failed . includes ( id )
} )
2018-12-18 17:01:28 +00:00
else
2019-01-03 04:49:56 +00:00
page . selected [ page . currentView ] = [ ]
2018-12-18 17:01:28 +00:00
2019-01-05 22:53:08 +00:00
localStorage [ lsKeys . selected [ page . currentView ] ] = JSON . stringify ( page . selected [ page . currentView ] )
page . getUploads ( page . views [ page . currentView ] )
2018-07-14 03:42:18 +00:00
} )
2018-04-28 23:44:25 +00:00
}
2018-07-14 03:42:18 +00:00
page . addSingleFileToAlbum = function ( id ) {
page . addFilesToAlbum ( [ id ] , function ( failed ) {
2018-12-18 17:01:28 +00:00
if ( ! failed ) return
2019-01-05 22:53:08 +00:00
page . getUploads ( page . views [ page . currentView ] )
2018-07-14 03:42:18 +00:00
} )
2018-03-30 02:39:53 +00:00
}
2018-07-14 03:42:18 +00:00
page . addFilesToAlbum = function ( ids , callback ) {
2018-10-09 19:52:41 +00:00
const count = ids . length
2018-09-26 11:57:33 +00:00
2018-10-09 19:52:41 +00:00
const content = document . createElement ( 'div' )
content . innerHTML = `
2018-10-18 13:26:40 +00:00
< div class = "field has-text-centered" >
< p > You are about to add < b > $ { count } < / b > f i l e $ { c o u n t = = = 1 ? ' ' : ' s ' } t o a n a l b u m . < / p >
< p > < b > If a file is already in an album , it will be moved . < / b > < / p >
< / d i v >
2018-10-09 19:52:41 +00:00
< div class = "field" >
< div class = "control" >
< div class = "select is-fullwidth" >
2018-10-10 17:33:11 +00:00
< select id = "swalAlbum" disabled >
2018-10-09 19:52:41 +00:00
< option value = "-1" > Remove from album < / o p t i o n >
< option value = "" selected disabled > Fetching albums list\u2026 < / o p t i o n >
< / s e l e c t >
< / d i v >
2018-10-10 17:33:11 +00:00
< / d i v >
2018-10-09 19:52:41 +00:00
< / d i v >
`
2018-09-26 11:57:33 +00:00
swal ( {
icon : 'warning' ,
2018-10-09 19:52:41 +00:00
content ,
2018-03-30 02:39:53 +00:00
buttons : {
cancel : true ,
confirm : {
2018-09-26 11:57:33 +00:00
text : 'OK' ,
2018-03-30 02:39:53 +00:00
closeModal : false
}
}
2018-09-26 11:57:33 +00:00
} ) . then ( function ( choose ) {
2018-12-18 17:01:28 +00:00
if ( ! choose ) return
2018-09-26 11:57:33 +00:00
2019-08-20 02:16:34 +00:00
const albumid = parseInt ( document . querySelector ( '#swalAlbum' ) . value )
2018-12-18 17:01:28 +00:00
if ( isNaN ( albumid ) )
2018-09-26 11:57:33 +00:00
return swal ( 'An error occurred!' , 'You did not choose an album.' , 'error' )
2018-07-14 03:42:18 +00:00
2018-09-26 11:57:33 +00:00
axios . post ( 'api/albums/addfiles' , {
2018-10-09 19:52:41 +00:00
ids ,
albumid
2018-09-26 11:57:33 +00:00
} ) . then ( function ( add ) {
2018-12-18 17:01:28 +00:00
if ( ! add ) return
2018-07-14 03:42:18 +00:00
2018-09-26 11:57:33 +00:00
if ( add . data . success === false ) {
2018-12-18 17:01:28 +00:00
if ( add . data . description === 'No token provided' )
2018-09-26 11:57:33 +00:00
page . verifyToken ( page . token )
2018-12-18 17:01:28 +00:00
else
2018-09-26 11:57:33 +00:00
swal ( 'An error occurred!' , add . data . description , 'error' )
2018-12-18 17:01:28 +00:00
2018-09-26 11:57:33 +00:00
return
}
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
let added = ids . length
2018-12-18 17:01:28 +00:00
if ( add . data . failed && add . data . failed . length )
2018-09-26 11:57:33 +00:00
added -= add . data . failed . length
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
const suffix = ` file ${ ids . length === 1 ? '' : 's' } `
2018-12-18 17:01:28 +00:00
if ( ! added )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , ` Could not add the ${ suffix } to the album. ` , 'error' )
2018-07-14 03:42:18 +00:00
2018-10-09 19:52:41 +00:00
swal ( 'Woohoo!' , ` Successfully ${ albumid < 0 ? 'removed' : 'added' } ${ added } ${ suffix } ${ albumid < 0 ? 'from' : 'to' } the album. ` , 'success' )
2019-09-08 01:56:29 +00:00
callback ( add . data . failed )
2018-09-26 11:57:33 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-09-26 11:57:33 +00:00
return swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
2018-03-30 02:39:53 +00:00
} )
2018-09-26 11:57:33 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-09-26 11:57:33 +00:00
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 ) {
2018-12-18 17:01:28 +00:00
if ( list . data . description === 'No token provided' )
2018-09-26 11:57:33 +00:00
page . verifyToken ( page . token )
2018-12-18 17:01:28 +00:00
else
2018-09-26 11:57:33 +00:00
swal ( 'An error occurred!' , list . data . description , 'error' )
2018-12-18 17:01:28 +00:00
2018-09-26 11:57:33 +00:00
return
}
2019-08-20 02:16:34 +00:00
const select = document . querySelector ( '#swalAlbum' )
2018-09-26 11:57:33 +00:00
// If the prompt was replaced, the container would be missing
2018-12-18 17:01:28 +00:00
if ( ! select ) return
2018-09-26 11:57:33 +00:00
select . innerHTML += list . data . albums
. map ( function ( album ) {
2018-10-09 19:52:41 +00:00
return ` <option value=" ${ album . id } "> ${ album . name } </option> `
2018-09-26 11:57:33 +00:00
} )
. join ( '\n' )
select . getElementsByTagName ( 'option' ) [ 1 ] . innerHTML = 'Choose an album'
select . removeAttribute ( 'disabled' )
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-09-26 11:57:33 +00:00
return swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
} )
2018-03-30 02:39:53 +00:00
}
2018-07-14 03:42:18 +00:00
page . getAlbums = function ( ) {
2018-10-09 19:52:41 +00:00
axios . get ( 'api/albums' ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( ! response ) return
2018-07-14 03:42:18 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
2018-07-14 03:42:18 +00:00
}
2018-05-06 14:14:57 +00:00
2018-10-09 19:52:41 +00:00
page . cache . albums = { }
page . dom . innerHTML = `
< h2 class = "subtitle" > Create new album < / h 2 >
2019-08-26 22:00:57 +00:00
< form class = "prevent-default" >
< div class = "field" >
< div class = "control" >
< input id = "albumName" class = "input" type = "text" placeholder = "Name" >
< / d i v >
2018-10-09 19:52:41 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< div class = "field" >
< div class = "control" >
< textarea id = "albumDescription" class = "textarea" placeholder = "Description" rows = "1" > < / t e x t a r e a >
< / d i v >
2018-12-13 09:09:46 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< div class = "field" >
< div class = "control" >
< button type = "submit" id = "submitAlbum" class = "button is-breeze is-fullwidth" data - action = "submit-album" >
< span class = "icon" >
< i class = "icon-paper-plane-empty" > < / i >
< / s p a n >
< span > Create < / s p a n >
< / b u t t o n >
< / d i v >
2018-10-09 19:52:41 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< / f o r m >
2018-10-09 19:52:41 +00:00
< hr >
< h2 class = "subtitle" > List of albums < / h 2 >
< div class = "table-container" >
< table class = "table is-fullwidth is-hoverable" >
< thead >
< tr >
< th > ID < / t h >
< th > Name < / t h >
< th > Files < / t h >
< th > Created at < / t h >
< th > Public link < / t h >
< th > < / t h >
< / t r >
< / t h e a d >
< tbody id = "table" >
< / t b o d y >
< / t a b l e >
< / d i v >
`
const homeDomain = response . data . homeDomain
2019-08-20 02:16:34 +00:00
const table = document . querySelector ( '#table' )
2018-10-09 19:52:41 +00:00
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 ,
2018-12-13 09:09:46 +00:00
public : album . public ,
description : album . description
2018-07-14 03:42:18 +00:00
}
2018-10-09 19:52:41 +00:00
const tr = document . createElement ( 'tr' )
tr . innerHTML = `
2018-10-12 10:19:14 +00:00
< th > $ { album . id } < / t h >
< th > $ { album . name } < / t h >
< th > $ { album . files } < / t h >
< td > $ { album . prettyDate } < / t d >
< td > < a $ { album . public ? ` href=" ${ albumUrl } " ` : 'class="is-linethrough"' } target = "_blank" rel = "noopener" > $ { albumUrl } < / a > < / t d >
< td style = "text-align: right" data - id = "${album.id}" >
< a class = "button is-small is-primary" title = "Edit album" data - action = "edit-album" >
< span class = "icon is-small" >
< i class = "icon-pencil-1" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-info clipboard-js" title = "Copy link to clipboard" $ { album . public ? ` data-clipboard-text=" ${ albumUrl } " ` : 'disabled' } >
< span class = "icon is-small" >
< i class = "icon-clipboard-1" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-warning" title = "Download album" $ { album . download ? ` href="api/album/zip/ ${ album . identifier } ?v= ${ album . editedAt } " ` : 'disabled' } >
< span class = "icon is-small" >
< i class = "icon-download" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-danger" title = "Delete album" data - action = "delete-album" >
< span class = "icon is-small" >
< i class = "icon-trash" > < / i >
< / s p a n >
< / a >
< / t d >
2018-10-09 19:52:41 +00:00
`
table . appendChild ( tr )
}
2019-09-08 01:56:29 +00:00
page . fadeAndScroll ( )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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 . editAlbum = function ( id ) {
2018-10-09 19:52:41 +00:00
const album = page . cache . albums [ id ]
2018-12-18 17:01:28 +00:00
if ( ! album ) return
2018-04-28 17:26:39 +00:00
2018-10-09 19:52:41 +00:00
const div = document . createElement ( 'div' )
div . innerHTML = `
< div class = "field" >
< div class = "controls" >
2018-12-13 09:09:46 +00:00
< input id = "swalName" class = "input" type = "text" placeholder = "Name" value = "${album.name || ''}" >
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< textarea id = "swalDescription" class = "textarea" placeholder = "Description" rows = "2" > $ { album . description || '' } < / t e x t a r e a >
2018-10-09 19:52:41 +00:00
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< label class = "checkbox" >
< input id = "swalDownload" type = "checkbox" $ { album . download ? '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" $ { album . public ? 'checked' : '' } >
Enable public link
< / l a b e l >
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< label class = "checkbox" >
< input id = "swalRequestLink" type = "checkbox" >
Request new 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-04-28 17:26:39 +00:00
title : 'Edit album' ,
2018-03-19 16:51:39 +00:00
icon : 'info' ,
2018-04-28 17:26:39 +00:00
content : div ,
2018-03-19 16:51:39 +00:00
buttons : {
cancel : true ,
confirm : {
closeModal : false
}
2018-01-23 20:06:30 +00:00
}
2018-10-09 19:52:41 +00:00
} ) . then ( function ( value ) {
2018-12-18 17:01:28 +00:00
if ( ! value ) return
2018-10-09 19:52:41 +00:00
axios . post ( 'api/albums/edit' , {
id ,
2019-09-08 01:56:29 +00:00
name : document . querySelector ( '#swalName' ) . value . trim ( ) ,
description : document . querySelector ( '#swalDescription' ) . value . trim ( ) ,
2019-08-20 02:16:34 +00:00
download : document . querySelector ( '#swalDownload' ) . checked ,
public : document . querySelector ( '#swalPublic' ) . checked ,
requestLink : document . querySelector ( '#swalRequestLink' ) . checked
2018-10-09 19:52:41 +00:00
} ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( ! response ) return
2018-10-09 19:52:41 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
}
2018-12-18 17:01:28 +00:00
if ( response . data . identifier )
2018-10-09 19:52:41 +00:00
swal ( 'Success!' , ` Your album's new identifier is: ${ response . data . identifier } . ` , 'success' )
2018-12-18 17:01:28 +00:00
else if ( response . data . name !== album . name )
2018-10-09 19:52:41 +00:00
swal ( 'Success!' , ` Your album was renamed to: ${ response . data . name } . ` , 'success' )
2018-12-18 17:01:28 +00:00
else
2018-10-09 19:52:41 +00:00
swal ( 'Success!' , 'Your album was edited!' , 'success' )
page . getAlbumsSidebar ( )
page . getAlbums ( )
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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-10-09 19:52:41 +00:00
} )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . deleteAlbum = function ( id ) {
swal ( {
2018-01-23 20:06:30 +00:00
title : 'Are you sure?' ,
2018-10-09 19:52:41 +00:00
text : 'This won\'t delete your uploads, only the album!' ,
2018-03-19 16:51:39 +00:00
icon : 'warning' ,
dangerMode : true ,
buttons : {
cancel : true ,
confirm : {
text : 'Yes, delete it!' ,
closeModal : false
2018-03-30 02:39:53 +00:00
} ,
purge : {
2018-10-09 19:52:41 +00:00
text : 'Umm, delete the uploads too please?' ,
2018-03-30 02:39:53 +00:00
value : 'purge' ,
className : 'swal-button--danger' ,
closeModal : false
2018-03-19 16:51:39 +00:00
}
}
2018-10-09 19:52:41 +00:00
} ) . then ( function ( proceed ) {
2018-12-18 17:01:28 +00:00
if ( ! proceed ) return
2018-01-23 20:06:30 +00:00
2018-10-09 19:52:41 +00:00
axios . post ( 'api/albums/delete' , {
id ,
purge : proceed === 'purge'
} ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-07-14 03:42:18 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
2019-09-08 01:56:29 +00:00
} else if ( Array . isArray ( response . data . failed ) && response . data . failed . length ) {
return swal ( 'An error occurred!' , 'Unable to delete ' , 'error' )
2018-07-14 03:42:18 +00:00
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
}
2018-01-23 20:06:30 +00:00
2018-10-09 19:52:41 +00:00
swal ( 'Deleted!' , 'Your album has been deleted.' , 'success' )
2018-07-14 03:42:18 +00:00
page . getAlbumsSidebar ( )
page . getAlbums ( )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-03-30 02:39:53 +00:00
return swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
2018-03-19 16:51:39 +00:00
} )
2018-10-09 19:52:41 +00:00
} )
}
page . submitAlbum = function ( element ) {
page . isLoading ( element , true )
axios . post ( 'api/albums' , {
2019-08-20 02:16:34 +00:00
name : document . querySelector ( '#albumName' ) . value ,
description : document . querySelector ( '#albumDescription' ) . value
2018-10-09 19:52:41 +00:00
} ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( ! response ) return
2018-10-09 19:52:41 +00:00
page . isLoading ( element , false )
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
}
2019-09-02 10:24:04 +00:00
swal ( 'Woohoo!' , 'Album was created successfully.' , 'success' )
2018-10-09 19:52:41 +00:00
page . getAlbumsSidebar ( )
page . getAlbums ( )
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
page . isLoading ( element , false )
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-05-06 14:14:57 +00:00
2018-07-14 03:42:18 +00:00
page . getAlbumsSidebar = function ( ) {
2018-10-09 19:52:41 +00:00
axios . get ( 'api/albums/sidebar' ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( ! response ) return
2018-07-14 03:42:18 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
2018-07-14 03:42:18 +00:00
}
2018-05-06 14:14:57 +00:00
2019-08-20 02:16:34 +00:00
const albumsContainer = document . querySelector ( '#albumsContainer' )
2018-10-09 19:52:41 +00:00
albumsContainer . innerHTML = ''
2018-05-06 14:14:57 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . albums === undefined ) return
2018-05-06 14:14:57 +00:00
2018-10-09 19:52:41 +00:00
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
2018-05-06 14:14:57 +00:00
2018-10-09 19:52:41 +00:00
a . addEventListener ( 'click' , function ( ) {
page . getAlbum ( this )
} )
2018-05-06 14:14:57 +00:00
2018-10-09 19:52:41 +00:00
li . appendChild ( a )
albumsContainer . appendChild ( li )
}
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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 . getAlbum = function ( album ) {
2018-04-29 12:47:24 +00:00
page . setActiveMenu ( album )
2018-10-13 19:35:46 +00:00
page . getUploads ( { album : album . id } )
2018-01-23 20:06:30 +00:00
}
2018-07-14 03:42:18 +00:00
page . changeToken = function ( ) {
2018-10-09 19:52:41 +00:00
axios . get ( 'api/tokens' ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
2018-07-14 03:42:18 +00:00
}
2018-10-09 19:52:41 +00:00
page . dom . innerHTML = `
< h2 class = "subtitle" > Manage your token < / h 2 >
< div class = "field" >
< label class = "label" > Your current token : < / l a b e l >
< div class = "field" >
< div class = "control" >
< input id = "token" readonly class = "input" type = "text" placeholder = "Your token" value = "${response.data.token}" >
< / d i v >
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< a id = "getNewToken" class = "button is-breeze is-fullwidth" data - action = "get-new-token" >
< span class = "icon" >
< i class = "icon-arrows-cw" > < / i >
< / s p a n >
< span > Request new token < / s p a n >
< / a >
< / d i v >
< / d i v >
`
2019-09-01 19:23:16 +00:00
page . fadeAndScroll ( )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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 . getNewToken = function ( element ) {
2018-04-29 12:47:24 +00:00
page . isLoading ( element , true )
2018-01-23 20:06:30 +00:00
2018-10-09 19:52:41 +00:00
axios . post ( 'api/tokens/change' ) . then ( function ( response ) {
page . isLoading ( element , false )
2018-07-14 03:42:18 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
2018-07-14 03:42:18 +00:00
}
2018-10-09 19:52:41 +00:00
swal ( {
title : 'Woohoo!' ,
text : 'Your token was successfully changed.' ,
icon : 'success'
} ) . then ( function ( ) {
axios . defaults . headers . common . token = response . data . token
2019-01-03 04:49:56 +00:00
localStorage [ lsKeys . token ] = response . data . token
2018-10-09 19:52:41 +00:00
page . token = response . data . token
page . changeToken ( )
2018-01-23 20:06:30 +00:00
} )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
page . isLoading ( element , false )
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 . changePassword = function ( ) {
2018-10-09 19:52:41 +00:00
page . dom . innerHTML = `
< h2 class = "subtitle" > Change your password < / h 2 >
2019-08-26 22:00:57 +00:00
< form class = "prevent-default" >
< div class = "field" >
< label class = "label" > New password : < / l a b e l >
< div class = "control" >
2019-09-08 01:56:29 +00:00
< input id = "password" class = "input" type = "password" min = "6" max = "64" >
2019-08-26 22:00:57 +00:00
< / d i v >
2018-10-09 19:52:41 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< div class = "field" >
< label class = "label" > Re - type new password : < / l a b e l >
< div class = "control" >
2019-09-08 01:56:29 +00:00
< input id = "passwordConfirm" class = "input" type = "password" min = "6" max = "64" >
2019-08-26 22:00:57 +00:00
< / d i v >
2018-10-09 19:52:41 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< div class = "field" >
< div class = "control" >
< button type = "submit" id = "sendChangePassword" class = "button is-breeze is-fullwidth" >
< span class = "icon" >
< i class = "icon-paper-plane-empty" > < / i >
< / s p a n >
< span > Set new password < / s p a n >
< / b u t t o n >
< / d i v >
2018-10-09 19:52:41 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< / f o r m >
2018-10-09 19:52:41 +00:00
`
2019-09-01 19:23:16 +00:00
page . fadeAndScroll ( )
2018-01-23 20:06:30 +00:00
2019-08-20 02:16:34 +00:00
document . querySelector ( '#sendChangePassword' ) . addEventListener ( 'click' , function ( ) {
if ( document . querySelector ( '#password' ) . value === document . querySelector ( '#passwordConfirm' ) . value )
page . sendNewPassword ( document . querySelector ( '#password' ) . value , this )
2018-12-18 17:01:28 +00:00
else
2018-01-23 20:06:30 +00:00
swal ( {
title : 'Password mismatch!' ,
text : 'Your passwords do not match, please try again.' ,
2018-03-19 16:51:39 +00:00
icon : 'error'
2018-01-23 20:06:30 +00:00
} )
} )
}
2018-07-14 03:42:18 +00:00
page . sendNewPassword = function ( pass , element ) {
2018-04-29 12:47:24 +00:00
page . isLoading ( element , true )
2018-01-23 20:06:30 +00:00
2018-10-09 19:52:41 +00:00
axios . post ( 'api/password/change' , { password : pass } ) . then ( function ( response ) {
page . isLoading ( element , false )
2018-07-14 03:42:18 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
if ( response . data . description === 'No token provided' ) {
return page . verifyToken ( page . token )
} else {
return swal ( 'An error occurred!' , response . data . description , 'error' )
2018-07-14 03:42:18 +00:00
}
2018-10-09 19:52:41 +00:00
swal ( {
title : 'Woohoo!' ,
text : 'Your password was successfully changed.' ,
icon : 'success'
} ) . then ( function ( ) {
page . changePassword ( )
2018-01-23 20:06:30 +00:00
} )
2018-10-09 19:52:41 +00:00
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
page . isLoading ( element , false )
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 . setActiveMenu = function ( activeItem ) {
2019-08-20 02:16:34 +00:00
const menu = document . querySelector ( '#menu' )
2018-10-09 19:52:41 +00:00
const items = menu . getElementsByTagName ( 'a' )
2018-12-18 17:01:28 +00:00
for ( let i = 0 ; i < items . length ; i ++ )
2018-07-14 04:35:31 +00:00
items [ i ] . classList . remove ( 'is-active' )
2018-01-23 20:06:30 +00:00
2018-05-01 14:41:25 +00:00
activeItem . classList . add ( 'is-active' )
2018-01-23 20:06:30 +00:00
}
2019-09-01 19:23:16 +00:00
page . getUsers = function ( { pageNum } = { } , element ) {
2018-12-18 17:01:28 +00:00
if ( element ) page . isLoading ( element , true )
if ( pageNum === undefined ) pageNum = 0
2018-10-09 19:52:41 +00:00
2018-12-18 17:01:28 +00:00
if ( ! page . permissions . admin )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , 'You can not do this!' , 'error' )
const url = ` api/users/ ${ pageNum } `
axios . get ( url ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
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
2018-12-18 17:01:28 +00:00
if ( element ) page . isLoading ( element , false )
2019-01-03 01:54:46 +00:00
return swal ( 'An error occurred!' , ` There are no more users to populate page ${ pageNum + 1 } . ` , 'error' )
2018-10-09 19:52:41 +00:00
}
page . currentView = 'users'
page . cache . users = { }
2019-01-01 19:39:08 +00:00
const pagination = page . paginate ( response . data . count , 25 , pageNum )
2018-10-09 19:52:41 +00:00
2019-01-03 04:49:56 +00:00
const extraControls = `
< div class = "columns" style = "margin-top: 10px" >
< div class = "column is-hidden-mobile" > < / d i v >
< div class = "column is-one-quarter" >
2019-08-26 22:00:57 +00:00
< form class = "prevent-default" >
< div class = "field has-addons" >
< div class = "control is-expanded" >
2019-09-08 01:56:29 +00:00
< input id = "jumpToPage" class = "input is-small" type = "number" value = "${pageNum + 1}" >
2019-08-26 22:00:57 +00:00
< / d i v >
< div class = "control" >
< button type = "submit" class = "button is-small is-breeze" title = "Jump to page" data - action = "jump-to-page" >
< span class = "icon" >
< i class = "icon-paper-plane-empty" > < / i >
< / s p a n >
< / b u t t o n >
< / d i v >
2019-01-03 04:49:56 +00:00
< / d i v >
2019-08-26 22:00:57 +00:00
< / f o r m >
2019-01-03 04:49:56 +00:00
< / d i v >
< / d i v >
`
2018-10-09 19:52:41 +00:00
const controls = `
< div class = "columns" >
< div class = "column is-hidden-mobile" > < / d i v >
< div class = "column" style = "text-align: right" >
< a class = "button is-small is-info" title = "Clear selection" data - action = "clear-selection" >
< span class = "icon" >
< i class = "icon-cancel" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-warning" title = "Bulk disable (WIP)" data - action = "bulk-disable-users" disabled >
< span class = "icon" >
< i class = "icon-hammer" > < / i >
< / s p a n >
< span > Bulk disable < / s p a n >
< / a >
< a class = "button is-small is-danger" title = "Bulk delete (WIP)" data - action = "bulk-delete-users" disabled >
< span class = "icon" >
< i class = "icon-trash" > < / i >
< / s p a n >
< span > Bulk delete < / s p a n >
< / a >
< / d i v >
< / d i v >
`
let allSelected = true
page . dom . innerHTML = `
$ { pagination }
2019-01-03 04:49:56 +00:00
$ { extraControls }
2018-10-09 19:52:41 +00:00
$ { controls }
< div class = "table-container" >
< table class = "table is-narrow is-fullwidth is-hoverable" >
< thead >
< tr >
< th > < input id = "selectAll" class = "checkbox" type = "checkbox" title = "Select all users" data - action = "select-all" > < / t h >
2018-10-12 09:42:16 +00:00
< th > ID < / t h >
2019-09-08 01:56:29 +00:00
< th style = "width: 20%" > Username < / t h >
2018-10-12 09:42:16 +00:00
< th > Uploads < / t h >
2018-10-12 10:19:14 +00:00
< th > Usage < / t h >
2018-10-09 19:52:41 +00:00
< th > Group < / t h >
< th > < / t h >
< / t r >
< / t h e a d >
< tbody id = "table" >
< / t b o d y >
< / t a b l e >
< / d i v >
< hr >
$ { pagination }
`
2019-08-20 02:16:34 +00:00
const table = document . querySelector ( '#table' )
2018-10-09 19:52:41 +00:00
for ( let i = 0 ; i < response . data . users . length ; i ++ ) {
const user = response . data . users [ i ]
const selected = page . selected . users . includes ( user . id )
2018-12-18 17:01:28 +00:00
if ( ! selected && allSelected ) allSelected = false
2018-10-09 19:52:41 +00:00
2018-10-10 17:33:11 +00:00
let displayGroup = null
2019-09-01 19:23:16 +00:00
const groups = Object . keys ( user . groups )
for ( let i = 0 ; i < groups . length ; i ++ ) {
if ( ! user . groups [ groups [ i ] ] ) break
displayGroup = groups [ i ]
2018-10-10 17:33:11 +00:00
}
2018-10-12 09:42:16 +00:00
// Server-side explicitly expects either of these two values to consider a user as disabled
const enabled = user . enabled !== false && user . enabled !== 0
2018-10-09 19:52:41 +00:00
page . cache . users [ user . id ] = {
username : user . username ,
groups : user . groups ,
2018-10-12 09:42:16 +00:00
enabled ,
2018-10-10 17:33:11 +00:00
displayGroup
2018-10-09 19:52:41 +00:00
}
const tr = document . createElement ( 'tr' )
tr . dataset . id = user . id
tr . innerHTML = `
2018-10-12 10:19:14 +00:00
< td class = "controls" > < input type = "checkbox" class = "checkbox" title = "Select this user" data - action = "select" $ { selected ? ' checked' : '' } > < / t d >
2018-10-12 09:42:16 +00:00
< th > $ { user . id } < / t h >
2018-10-12 10:19:14 +00:00
< th$ { enabled ? '' : ' class="is-linethrough"' } > $ { user . username } < / t d >
2018-10-12 09:42:16 +00:00
< th > $ { user . uploadsCount } < / t h >
2018-10-12 10:19:14 +00:00
< td > $ { page . getPrettyBytes ( user . diskUsage ) } < / t d >
2018-10-10 17:33:11 +00:00
< td > $ { displayGroup } < / t d >
2018-10-09 19:52:41 +00:00
< td class = "controls" style = "text-align: right" >
< a class = "button is-small is-primary" title = "Edit user" data - action = "edit-user" >
< span class = "icon" >
< i class = "icon-pencil-1" > < / i >
< / s p a n >
< / a >
2019-01-03 04:49:56 +00:00
< a class = "button is-small is-info" title = "View uploads" data - action = "view-user-uploads" $ { user . uploadsCount ? '' : 'disabled' } >
< span class = "icon" >
2019-01-03 04:54:20 +00:00
< i class = "icon-docs" > < / i >
2019-01-03 04:49:56 +00:00
< / s p a n >
< / a >
2019-01-01 19:39:08 +00:00
< a class = "button is-small is-warning" title = "Disable user" data - action = "disable-user" $ { enabled ? '' : 'disabled' } >
2018-10-09 19:52:41 +00:00
< span class = "icon" >
< i class = "icon-hammer" > < / i >
< / s p a n >
< / a >
< a class = "button is-small is-danger" title = "Delete user (WIP)" data - action = "delete-user" disabled >
< span class = "icon" >
< i class = "icon-trash" > < / i >
< / s p a n >
< / a >
< / t d >
`
table . appendChild ( tr )
page . checkboxes . users = Array . from ( table . querySelectorAll ( '.checkbox[data-action="select"]' ) )
}
2019-09-08 01:56:29 +00:00
page . fadeAndScroll ( )
2018-10-09 19:52:41 +00:00
if ( allSelected && response . data . users . length ) {
2019-08-20 02:16:34 +00:00
const selectAll = document . querySelector ( '#selectAll' )
2018-12-18 17:01:28 +00:00
if ( selectAll ) selectAll . checked = true
2018-10-09 19:52:41 +00:00
}
page . views . users . pageNum = response . data . users . length ? pageNum : 0
} ) . catch ( function ( error ) {
2018-12-18 17:01:28 +00:00
if ( element ) page . isLoading ( element , false )
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
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 ]
2018-12-18 17:01:28 +00:00
if ( ! user ) return
2018-10-09 19:52:41 +00:00
2019-01-01 19:39:08 +00:00
const groupOptions = Object . keys ( page . permissions ) . map ( function ( g , i , a ) {
2018-10-10 17:33:11 +00:00
const selected = g === user . displayGroup
const disabled = ! ( a [ i + 1 ] && page . permissions [ a [ i + 1 ] ] )
return ` <option value=" ${ g } " ${ selected ? ' selected' : '' } ${ disabled ? ' disabled' : '' } > ${ g } </option> `
} ) . join ( '\n' )
2018-10-09 19:52:41 +00:00
const div = document . createElement ( 'div' )
div . innerHTML = `
< div class = "field" >
< label class = "label" > Username < / l a b e l >
< div class = "controls" >
< input id = "swalUsername" class = "input" type = "text" value = "${user.username || ''}" >
< / d i v >
< / d i v >
2018-10-10 17:33:11 +00:00
< div class = "field" >
< label class = "label" > User group < / l a b e l >
< div class = "control" >
< div class = "select is-fullwidth" >
< select id = "swalGroup" >
$ { groupOptions }
< / s e l e c t >
< / d i v >
< / d i v >
< / d i v >
2018-10-09 19:52:41 +00:00
< div class = "field" >
< div class = "control" >
< label class = "checkbox" >
< input id = "swalEnabled" type = "checkbox" $ { user . enabled ? 'checked' : '' } >
Enabled
< / l a b e l >
< / d i v >
< / d i v >
< div class = "field" >
< div class = "control" >
< label class = "checkbox" >
< input id = "swalResetPassword" type = "checkbox" >
Reset password
< / l a b e l >
< / d i v >
< / d i v >
`
swal ( {
title : 'Edit user' ,
icon : 'info' ,
content : div ,
buttons : {
cancel : true ,
confirm : {
closeModal : false
}
}
2019-01-01 19:39:08 +00:00
} ) . then ( function ( proceed ) {
if ( ! proceed ) return
2018-10-09 19:52:41 +00:00
axios . post ( 'api/users/edit' , {
id ,
2019-08-20 02:16:34 +00:00
username : document . querySelector ( '#swalUsername' ) . value ,
group : document . querySelector ( '#swalGroup' ) . value ,
enabled : document . querySelector ( '#swalEnabled' ) . checked ,
resetPassword : document . querySelector ( '#swalResetPassword' ) . checked
2018-10-09 19:52:41 +00:00
} ) . then ( function ( response ) {
2018-12-18 17:01:28 +00:00
if ( ! response ) return
2018-10-09 19:52:41 +00:00
2018-12-18 17:01:28 +00:00
if ( response . data . success === false )
2018-10-09 19:52:41 +00:00
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 = `
< p > $ { user . username } ' s new password is : < / p >
2019-09-08 01:56:29 +00:00
< p > < code > $ { response . data . password } < / c o d e > < / p >
2018-10-09 19:52:41 +00:00
`
swal ( {
title : 'Success!' ,
icon : 'success' ,
content : div
} )
2019-01-01 19:39:08 +00:00
} else if ( response . data . update && response . data . update . username !== user . username ) {
swal ( 'Success!' , ` ${ user . username } was renamed into: ${ response . data . update . name } . ` , 'success' )
2018-12-18 17:41:42 +00:00
} else {
2018-10-09 19:52:41 +00:00
swal ( 'Success!' , 'The user was edited!' , 'success' )
2018-12-18 17:41:42 +00:00
}
2018-10-09 19:52:41 +00:00
page . getUsers ( page . views . users )
} ) . catch ( function ( error ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
} )
} )
}
page . disableUser = function ( id ) {
2019-01-01 19:39:08 +00:00
const user = page . cache . users [ id ]
if ( ! user || ! user . enabled ) return
const content = document . createElement ( 'div' )
content . innerHTML = ` You will be disabling a user with the username <b> ${ page . cache . users [ id ] . username } </b>! `
2018-10-09 19:52:41 +00:00
swal ( {
title : 'Are you sure?' ,
icon : 'warning' ,
2019-01-01 19:39:08 +00:00
content ,
2018-10-09 19:52:41 +00:00
dangerMode : true ,
buttons : {
cancel : true ,
confirm : {
text : 'Yes, disable them!' ,
closeModal : false
}
}
} ) . then ( function ( proceed ) {
2018-12-18 17:41:42 +00:00
if ( ! proceed ) return
2018-10-09 19:52:41 +00:00
axios . post ( 'api/users/disable' , { id } ) . then ( function ( response ) {
2018-12-18 17:41:42 +00:00
if ( ! response ) return
2018-10-09 19:52:41 +00:00
2019-01-01 19:39:08 +00:00
if ( response . data . success === false )
2018-12-18 17:41:42 +00:00
if ( response . data . description === 'No token provided' )
2018-10-09 19:52:41 +00:00
return page . verifyToken ( page . token )
2018-12-18 17:41:42 +00:00
else
2018-10-09 19:52:41 +00:00
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 ) {
2019-09-08 01:56:29 +00:00
console . error ( error )
2018-10-09 19:52:41 +00:00
return swal ( 'An error occurred!' , 'There was an error with the request, please check the console for more information.' , 'error' )
} )
} )
2018-10-08 18:54:16 +00:00
}
2019-01-01 19:39:08 +00:00
page . paginate = function ( totalItems , itemsPerPage , currentPage ) {
// Roughly based on https://github.com/mayuska/pagination/blob/master/index.js
currentPage = currentPage + 1
const step = 3
const numPages = Math . ceil ( totalItems / itemsPerPage )
let template = ''
const elementsToShow = step * 2
const add = {
pageNum ( start , end ) {
for ( let i = start ; i <= end ; ++ i )
2019-01-07 22:54:12 +00:00
template += ` <li><a class="button pagination-link ${ i === currentPage ? ' is-current' : '' } " aria-label="Goto page ${ i } " data-action="page-goto" data-goto=" ${ i - 1 } "> ${ i } </a></li> `
2019-01-01 19:39:08 +00:00
} ,
startDots ( ) {
template += `
2019-01-07 22:54:12 +00:00
< li > < a class = "button pagination-link" aria - label = "Goto page 1" data - action = "page-goto" data - goto = "0" > 1 < / a > < / l i >
2019-08-26 22:23:54 +00:00
< li data - action = "page-ellipsis" > < span class = "pagination-ellipsis" > & hellip ; < / s p a n > < / l i >
2019-01-01 19:39:08 +00:00
`
} ,
endDots ( ) {
template += `
2019-08-26 22:23:54 +00:00
< li data - action = "page-ellipsis" > < span class = "pagination-ellipsis" > & hellip ; < / s p a n > < / l i >
2019-01-07 22:54:12 +00:00
< li > < a class = "button pagination-link" aria - label = "Goto page ${numPages}" data - action = "page-goto" data - goto = "${numPages - 1}" > $ { numPages } < / a > < / l i >
2019-01-01 19:39:08 +00:00
`
}
}
2019-06-17 19:34:15 +00:00
if ( elementsToShow + 1 >= numPages ) {
2019-01-01 19:39:08 +00:00
add . pageNum ( 1 , numPages )
} else if ( currentPage < elementsToShow ) {
add . pageNum ( 1 , elementsToShow )
add . endDots ( )
2019-06-17 19:34:15 +00:00
} else if ( currentPage > numPages - elementsToShow + 1 ) {
2019-01-01 19:39:08 +00:00
add . startDots ( )
2019-06-17 19:34:15 +00:00
add . pageNum ( numPages - elementsToShow + 1 , numPages )
2019-01-01 19:39:08 +00:00
} else {
add . startDots ( )
2019-06-17 19:34:15 +00:00
add . pageNum ( currentPage - step + 1 , currentPage + step - 1 )
2019-01-01 19:39:08 +00:00
add . endDots ( )
}
return `
< nav class = "pagination is-centered is-small" >
< a class = "button pagination-previous" data - action = "page-prev" > Previous < / a >
< a class = "button pagination-next" data - action = "page-next" > Next page < / a >
< ul class = "pagination-list" > $ { template } < / u l >
< / n a v >
`
}
2018-10-08 18:54:16 +00:00
2019-04-05 17:32:52 +00:00
page . getServerStats = function ( element ) {
if ( ! page . permissions . admin )
return swal ( 'An error occurred!' , 'You can not do this!' , 'error' )
2019-06-18 18:48:30 +00:00
page . dom . innerHTML = `
Please wait , this may take a while \u2026
< progress class = "progress is-breeze" max = "100" style = "margin-top: 10px" > < / p r o g r e s s >
`
2019-09-01 19:23:16 +00:00
page . fadeAndScroll ( )
2019-06-18 18:48:30 +00:00
2019-04-05 17:32:52 +00:00
const url = 'api/stats'
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' )
}
2019-04-12 00:45:33 +00:00
let content = ''
2019-09-01 19:23:16 +00:00
const keys = Object . keys ( response . data . stats )
for ( let i = 0 ; i < keys . length ; i ++ ) {
2019-04-12 00:45:33 +00:00
let rows = ''
2019-09-08 01:56:29 +00:00
if ( ! response . data . stats [ keys [ i ] ] )
2019-04-12 00:45:33 +00:00
rows += `
< tr >
2019-06-03 19:40:24 +00:00
< td > Generating , please try again later\u2026 < / t d >
< td > < / t d >
2019-04-12 00:45:33 +00:00
< / t r >
`
2019-09-08 01:56:29 +00:00
else
try {
const valKeys = Object . keys ( response . data . stats [ keys [ i ] ] )
for ( let j = 0 ; j < valKeys . length ; j ++ ) {
const _value = response . data . stats [ keys [ i ] ] [ valKeys [ j ] ]
let value = _value
if ( [ 'albums' , 'users' , 'uploads' ] . includes ( keys [ i ] ) )
value = _value . toLocaleString ( )
if ( [ 'memoryUsage' , 'size' ] . includes ( valKeys [ j ] ) )
value = page . getPrettyBytes ( _value )
if ( valKeys [ j ] === 'systemMemory' )
value = ` ${ page . getPrettyBytes ( _value . used ) } / ${ page . getPrettyBytes ( _value . total ) } ( ${ Math . round ( _value . used / _value . total * 100 ) } %) `
rows += `
< tr >
< th > $ { valKeys [ j ] . replace ( /([A-Z])/g , ' $1' ) . toUpperCase ( ) } < / t h >
< td > $ { value } < / t d >
< / t r >
`
}
} catch ( error ) {
console . error ( error )
rows = `
< tr >
< td > Error parsing response . Try again ? < / t d >
< td > < / t d >
< / t r >
`
2019-06-03 19:40:24 +00:00
}
2019-04-12 00:45:33 +00:00
content += `
< div class = "table-container" >
< table class = "table is-fullwidth is-hoverable" >
< thead >
< tr >
2019-09-01 19:23:16 +00:00
< th > $ { keys [ i ] . toUpperCase ( ) } < / t h >
2019-04-12 00:45:33 +00:00
< td style = "width: 50%" > < / t d >
< / t r >
< / t h e a d >
< tbody >
$ { rows }
< / t b o d y >
< / t a b l e >
< / d i v >
2019-04-05 17:32:52 +00:00
`
}
page . dom . innerHTML = `
< h2 class = "subtitle" > Statistics < / h 2 >
2019-04-12 00:45:33 +00:00
$ { content }
2019-04-05 17:32:52 +00:00
`
2019-09-01 19:23:16 +00:00
page . fadeAndScroll ( )
2019-04-05 17:32:52 +00:00
} )
}
2018-07-14 03:42:18 +00:00
window . onload = function ( ) {
2018-03-28 11:36:28 +00:00
// Add 'no-touch' class to non-touch devices
2018-12-18 17:01:28 +00:00
if ( ! ( 'ontouchstart' in document . documentElement ) )
2018-05-01 14:41:25 +00:00
document . documentElement . classList . add ( 'no-touch' )
2018-03-28 20:05:01 +00:00
2019-01-03 04:49:56 +00:00
const selectedKeys = [ 'uploads' , 'uploadsAll' , 'users' ]
2019-09-01 19:23:16 +00:00
for ( let i = 0 ; i < selectedKeys . length ; i ++ ) {
const ls = localStorage [ lsKeys . selected [ selectedKeys [ i ] ] ]
if ( ls ) page . selected [ selectedKeys [ i ] ] = JSON . parse ( ls )
2018-03-29 23:22:08 +00:00
}
2018-04-29 12:47:24 +00:00
page . preparePage ( )
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
page . lazyLoad = new LazyLoad ( )
2018-01-23 20:06:30 +00:00
}