diff --git a/controllers/albumsController.js b/controllers/albumsController.js index 5c2fb85..427655d 100644 --- a/controllers/albumsController.js +++ b/controllers/albumsController.js @@ -328,7 +328,7 @@ self.get = async (req, res, next) => { const files = await db.table('files') .select('name') .where('albumid', album.id) - .orderBy('id', 'DESC') + .orderBy('id', 'desc') for (const file of files) { file.file = `${config.domain}/${file.name}` diff --git a/controllers/uploadController.js b/controllers/uploadController.js index 8b2f9ab..2184007 100644 --- a/controllers/uploadController.js +++ b/controllers/uploadController.js @@ -775,6 +775,18 @@ self.list = async (req, res) => { } } + // Cast column(s) to specific type if they're stored differently + const _orderByCasts = { + size: 'integer' + } + // Columns with which to use SQLite's NULLS LAST option + const _orderByNullsLast = [ + 'userid', + 'expirydate', + 'ip' + ] + const _orderBy = [] + // Perhaps this can be simplified even further? if (filters) { const usernames = [] @@ -797,11 +809,26 @@ self.list = async (req, res) => { }) .forEach(v => { if (!v) return - if (v[0] === 'user') usernames.push(v[1]) - else if (v[0] === 'name') _filters.names.push(v[1]) - else if (v[0] === 'ip') _filters.ips.push(v[1]) - else if (v[0] === '-user') _filters.flags.nouser = true - else if (v[0] === '-ip') _filters.flags.noip = true + if (v[0] === 'user') { + usernames.push(v[1]) + } else if (v[0] === 'name') { + _filters.names.push(v[1]) + } else if (v[0] === 'ip') { + _filters.ips.push(v[1]) + } else if (v[0] === '-user') { + _filters.flags.nouser = true + } else if (v[0] === '-ip') { + _filters.flags.noip = true + } else if (v[0] === 'orderby') { + const tmp = v[1].split(':') + let col = tmp[0] + let dir = 'asc' + if (_orderByCasts[col]) + col = `cast (\`${col}\` as ${_orderByCasts[col]})` + if (tmp[1] && /^d/i.test(tmp[1])) + dir = 'desc' + _orderBy.push(`${col} ${dir}${_orderByNullsLast.includes(col) ? ' nulls last' : ''}`) + } }) _filters.uploaders = await db.table('users') .whereIn('username', usernames) @@ -855,7 +882,7 @@ self.list = async (req, res) => { const files = await db.table('files') .where(filter) - .orderBy('id', 'DESC') + .orderByRaw(_orderBy.length ? _orderBy.join(', ') : '`id` desc') .limit(25) .offset(25 * offset) .select(columns) diff --git a/routes/album.js b/routes/album.js index dc73da5..0f493b6 100644 --- a/routes/album.js +++ b/routes/album.js @@ -59,7 +59,7 @@ routes.get('/a/:identifier', async (req, res, next) => { const files = await db.table('files') .select('name', 'size') .where('albumid', album.id) - .orderBy('id', 'DESC') + .orderBy('id', 'desc') album.thumb = '' album.totalSize = 0 diff --git a/src/js/dashboard.js b/src/js/dashboard.js index a25ebcf..32da320 100644 --- a/src/js/dashboard.js +++ b/src/js/dashboard.js @@ -949,26 +949,32 @@ page.filtersHelp = element => { content.innerHTML = ` This supports 3 filter keys, namely user (username), ip and name (upload name). Each key can be specified more than once. - Backlashes should be used if the usernames have spaces. - There are also 2 additional flags, namely -user and -ip, which will match uploads by non-registered users and have no IPs respectively. + Backslashes should be used if the username contain whitespaces. - How does it work? - First, it will filter uploads matching ANY of the supplied user or ip keys. - Then, it will refine the matches using the supplied name keys. + There are 2 special flags, namely -user and -ip, which will match uploads by non-registered users and have no IPs respectively. - Examples: + Matches can also be sorted with orderby:columnName[:direction] key. + This key requires using the internal column names used in the database (size, timestamp, expirydate, and so on). + This key can also be specified more than once, where their order will decide the sorting steps. + Internals: + First, it will filter uploads matching ANY of the supplied filter keys AND/OR special flags, if any. + Second, it will refine the matches using the supplied name keys, if any. + Third, it will sort the matches using the supplied orderby keys, if any. + + Examples: Uploads from user with username "demo": user:demo - - Uploads from users with username either "John Doe" OR "demo": + Uploads from users with username "John Doe" AND/OR "demo": user:John\\ Doe user:demo - Uploads from IP "127.0.0.1" AND which upload names match "*.rar" OR "*.zip": ip:127.0.0.1 name:*.rar name:*.zip - - Uploads from user with username "test" OR from non-registered users: + Uploads from user with username "test" AND/OR from non-registered users: user:test -user + Sort results by "size" column in ascending and descending order respectively: + orderby:expirydate + user:demo orderby:size + -user name:*.mp4 orderby:size:desc `.trim().replace(/^ {6}/gm, '').replace(/\n/g, '
') swal({ content }) }