mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Change:Series volume numbers to use language sensitive sorting #261
This commit is contained in:
		
							parent
							
								
									49fcaefd01
								
							
						
					
					
						commit
						ef94a6bb29
					
				| @ -15,6 +15,7 @@ const BackupController = require('./controllers/BackupController') | |||||||
| 
 | 
 | ||||||
| const BookFinder = require('./BookFinder') | const BookFinder = require('./BookFinder') | ||||||
| const AuthorFinder = require('./AuthorFinder') | const AuthorFinder = require('./AuthorFinder') | ||||||
|  | const FileSystemController = require('./controllers/FileSystemController') | ||||||
| 
 | 
 | ||||||
| class ApiController { | class ApiController { | ||||||
|   constructor(MetadataPath, db, auth, streamManager, rssFeeds, downloadManager, coverController, backupManager, watcher, cacheManager, emitter, clientEmitter) { |   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/covers', this.findCovers.bind(this)) | ||||||
|     this.router.get('/search/books', this.findBooks.bind(this)) |     this.router.get('/search/books', this.findBooks.bind(this)) | ||||||
| 
 | 
 | ||||||
|  |     //
 | ||||||
|  |     // File System Routes
 | ||||||
|  |     //
 | ||||||
|  |     this.router.get('/filesystem', FileSystemController.getPaths.bind(this)) | ||||||
|  | 
 | ||||||
|     //
 |     //
 | ||||||
|     // Others
 |     // Others
 | ||||||
|     //
 |     //
 | ||||||
| @ -163,8 +169,6 @@ class ApiController { | |||||||
| 
 | 
 | ||||||
|     this.router.get('/download/:id', this.download.bind(this)) |     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('/syncUserAudiobookData', this.syncUserAudiobookData.bind(this)) | ||||||
| 
 | 
 | ||||||
|     this.router.post('/purgecache', this.purgeCache.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) { |   async syncUserAudiobookData(req, res) { | ||||||
|     if (!req.body.data) { |     if (!req.body.data) { | ||||||
|       return res.status(403).send('Invalid local user audiobook data') |       return res.status(403).send('Invalid local user audiobook data') | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								server/controllers/FileSystemController.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								server/controllers/FileSystemController.js
									
									
									
									
									
										Normal file
									
								
							| @ -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() | ||||||
| @ -189,12 +189,9 @@ class LibraryController { | |||||||
|     if (!audiobooks.length) { |     if (!audiobooks.length) { | ||||||
|       return res.status(404).send('Series not found') |       return res.status(404).send('Series not found') | ||||||
|     } |     } | ||||||
|     audiobooks = sort(audiobooks).asc(ab => { |     var sortedBooks = libraryHelpers.sortSeriesBooks(audiobooks, false) | ||||||
|       if (!isNaN(ab.book.volumeNumber) && ab.book.volumeNumber !== null) return Number(ab.book.volumeNumber) |  | ||||||
|       return ab.book.volumeNumber |  | ||||||
|     }) |  | ||||||
|     res.json({ |     res.json({ | ||||||
|       results: audiobooks.map(ab => ab.toJSONExpanded()), |       results: sortedBooks, | ||||||
|       total: audiobooks.length |       total: audiobooks.length | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -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 = { | module.exports = { | ||||||
|   decode(text) { |   decode(text) { | ||||||
| @ -92,14 +95,18 @@ module.exports = { | |||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|     return Object.values(_series).map((series) => { |     return Object.values(_series).map((series) => { | ||||||
|       series.books = sort(series.books).asc(ab => { |       series.books = naturalSort(series.books).asc(ab => ab.book.volumeNumber) | ||||||
|         if (!isNaN(ab.book.volumeNumber) && ab.book.volumeNumber !== null) return Number(ab.book.volumeNumber) |  | ||||||
|         return ab.book.volumeNumber |  | ||||||
|       }) |  | ||||||
|       return series |       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) { |   getBooksWithUserAudiobook(user, books) { | ||||||
|     return books.map(book => { |     return books.map(book => { | ||||||
|       return { |       return { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user