diff --git a/server/ApiController.js b/server/ApiController.js index cfd99cac..2fe3315d 100644 --- a/server/ApiController.js +++ b/server/ApiController.js @@ -15,6 +15,7 @@ const BackupController = require('./controllers/BackupController') const BookFinder = require('./BookFinder') const AuthorFinder = require('./AuthorFinder') +const FileSystemController = require('./controllers/FileSystemController') class ApiController { constructor(MetadataPath, db, auth, streamManager, rssFeeds, downloadManager, coverController, backupManager, watcher, cacheManager, emitter, clientEmitter) { @@ -145,6 +146,11 @@ class ApiController { this.router.get('/search/covers', this.findCovers.bind(this)) this.router.get('/search/books', this.findBooks.bind(this)) + // + // File System Routes + // + this.router.get('/filesystem', FileSystemController.getPaths.bind(this)) + // // Others // @@ -163,8 +169,6 @@ class ApiController { this.router.get('/download/:id', this.download.bind(this)) - this.router.get('/filesystem', this.getFileSystemPaths.bind(this)) - this.router.post('/syncUserAudiobookData', this.syncUserAudiobookData.bind(this)) this.router.post('/purgecache', this.purgeCache.bind(this)) @@ -339,25 +343,6 @@ class ApiController { } } - async getFileSystemPaths(req, res) { - var excludedDirs = ['node_modules', 'client', 'server', '.git', 'static', 'build', 'dist', 'metadata', 'config', 'sys', 'proc'].map(dirname => { - return Path.sep + dirname - }) - - // Do not include existing mapped library paths in response - this.db.libraries.forEach(lib => { - lib.folders.forEach((folder) => { - var dir = folder.fullPath - if (dir.includes(global.appRoot)) dir = dir.replace(global.appRoot, '') - excludedDirs.push(dir) - }) - }) - - Logger.debug(`[Server] get file system paths, excluded: ${excludedDirs.join(', ')}`) - var dirs = await this.getDirectories(global.appRoot, '/', excludedDirs) - res.json(dirs) - } - async syncUserAudiobookData(req, res) { if (!req.body.data) { return res.status(403).send('Invalid local user audiobook data') diff --git a/server/controllers/FileSystemController.js b/server/controllers/FileSystemController.js new file mode 100644 index 00000000..28d63571 --- /dev/null +++ b/server/controllers/FileSystemController.js @@ -0,0 +1,25 @@ +const Logger = require('../Logger') + +class FileSystemController { + constructor() { } + + async getPaths(req, res) { + var excludedDirs = ['node_modules', 'client', 'server', '.git', 'static', 'build', 'dist', 'metadata', 'config', 'sys', 'proc'].map(dirname => { + return Path.sep + dirname + }) + + // Do not include existing mapped library paths in response + this.db.libraries.forEach(lib => { + lib.folders.forEach((folder) => { + var dir = folder.fullPath + if (dir.includes(global.appRoot)) dir = dir.replace(global.appRoot, '') + excludedDirs.push(dir) + }) + }) + + Logger.debug(`[Server] get file system paths, excluded: ${excludedDirs.join(', ')}`) + var dirs = await this.getDirectories(global.appRoot, '/', excludedDirs) + res.json(dirs) + } +} +module.exports = new FileSystemController() \ No newline at end of file diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index f0963cef..0980b156 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -189,12 +189,9 @@ class LibraryController { if (!audiobooks.length) { return res.status(404).send('Series not found') } - audiobooks = sort(audiobooks).asc(ab => { - if (!isNaN(ab.book.volumeNumber) && ab.book.volumeNumber !== null) return Number(ab.book.volumeNumber) - return ab.book.volumeNumber - }) + var sortedBooks = libraryHelpers.sortSeriesBooks(audiobooks, false) res.json({ - results: audiobooks.map(ab => ab.toJSONExpanded()), + results: sortedBooks, total: audiobooks.length }) } diff --git a/server/utils/libraryHelpers.js b/server/utils/libraryHelpers.js index 10bb4af4..2d012587 100644 --- a/server/utils/libraryHelpers.js +++ b/server/utils/libraryHelpers.js @@ -1,4 +1,7 @@ -const { sort } = require('fast-sort') +const { sort, createNewSortInstance } = require('fast-sort') +const naturalSort = createNewSortInstance({ + comparer: new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }).compare +}) module.exports = { decode(text) { @@ -92,14 +95,18 @@ module.exports = { } }) return Object.values(_series).map((series) => { - series.books = sort(series.books).asc(ab => { - if (!isNaN(ab.book.volumeNumber) && ab.book.volumeNumber !== null) return Number(ab.book.volumeNumber) - return ab.book.volumeNumber - }) + series.books = naturalSort(series.books).asc(ab => ab.book.volumeNumber) return series }) }, + sortSeriesBooks(books, minified = false) { + return naturalSort(books).asc(ab => ab.book.volumeNumber).map(ab => { + if (minified) return ab.toJSONMinified() + return ab.toJSONExpanded() + }) + }, + getBooksWithUserAudiobook(user, books) { return books.map(book => { return {