Update global search, fix toggling between automated backup, add open search cover in new tab #83

This commit is contained in:
advplyr 2021-10-09 11:09:06 -05:00
parent 59d12ef5de
commit 32bc9d5282
16 changed files with 254 additions and 52 deletions

View file

@ -30,6 +30,7 @@ class ApiController {
this.router.get('/find/:method', this.find.bind(this))
this.router.get('/libraries', this.getLibraries.bind(this))
this.router.get('/library/:id/search', this.searchLibrary.bind(this))
this.router.get('/library/:id', this.getLibrary.bind(this))
this.router.delete('/library/:id', this.deleteLibrary.bind(this))
this.router.patch('/library/:id', this.updateLibrary.bind(this))
@ -97,6 +98,53 @@ class ApiController {
res.json(libraries)
}
searchLibrary(req, res) {
var library = this.db.libraries.find(lib => lib.id === req.params.id)
if (!library) {
return res.status(404).send('Library not found')
}
if (!req.query.q) {
return res.status(400).send('No query string')
}
var maxResults = req.query.max || 3
var bookMatches = []
var authorMatches = {}
var seriesMatches = {}
var audiobooksInLibrary = this.db.audiobooks.filter(ab => ab.libraryId === library.id)
audiobooksInLibrary.forEach((ab) => {
var queryResult = ab.searchQuery(req.query.q)
if (queryResult.book) {
bookMatches.push({
audiobook: ab,
matchKey: queryResult.book
})
}
if (queryResult.author && !authorMatches[queryResult.author]) {
authorMatches[queryResult.author] = {
author: queryResult.author
}
}
if (queryResult.series) {
if (!seriesMatches[queryResult.series]) {
seriesMatches[queryResult.series] = {
series: queryResult.series,
audiobooks: [ab]
}
} else {
seriesMatches[queryResult.series].audiobooks.push(ab)
}
}
})
res.json({
audiobooks: bookMatches.slice(0, maxResults),
authors: Object.values(authorMatches).slice(0, maxResults),
series: Object.values(seriesMatches).slice(0, maxResults)
})
}
getLibrary(req, res) {
var library = this.db.libraries.find(lib => lib.id === req.params.id)
if (!library) {
@ -563,8 +611,14 @@ class ApiController {
if (!settingsUpdate || !isObject(settingsUpdate)) {
return res.status(500).send('Invalid settings update object')
}
var madeUpdates = this.db.serverSettings.update(settingsUpdate)
if (madeUpdates) {
// If backup schedule is updated - update backup manager
if (settingsUpdate.backupSchedule !== undefined) {
this.backupManager.updateCronSchedule()
}
await this.db.updateEntity('settings', this.db.serverSettings)
}
return res.json({

View file

@ -21,6 +21,8 @@ class BackupManager {
this.Gid = Gid
this.db = db
this.scheduleTask = null
this.backups = []
}
@ -28,7 +30,7 @@ class BackupManager {
return this.db.serverSettings || {}
}
async init(overrideCron = null) {
async init() {
var backupsDirExists = await fs.pathExists(this.BackupPath)
if (!backupsDirExists) {
await fs.ensureDir(this.BackupPath)
@ -36,16 +38,34 @@ class BackupManager {
}
await this.loadBackups()
this.scheduleCron()
}
scheduleCron() {
if (!this.serverSettings.backupSchedule) {
Logger.info(`[BackupManager] Auto Backups are disabled`)
return
}
try {
var cronSchedule = overrideCron || this.serverSettings.backupSchedule
cron.schedule(cronSchedule, this.runBackup.bind(this))
var cronSchedule = this.serverSettings.backupSchedule
this.scheduleTask = cron.schedule(cronSchedule, this.runBackup.bind(this))
} catch (error) {
Logger.error(`[BackupManager] Failed to schedule backup cron ${this.serverSettings.backupSchedule}`)
Logger.error(`[BackupManager] Failed to schedule backup cron ${this.serverSettings.backupSchedule}`, error)
}
}
updateCronSchedule() {
if (this.scheduleTask && !this.serverSettings.backupSchedule) {
Logger.info(`[BackupManager] Disabling backup schedule`)
if (this.scheduleTask.destroy) this.scheduleTask.destroy()
this.scheduleTask = null
} else if (!this.scheduleTask && this.serverSettings.backupSchedule) {
Logger.info(`[BackupManager] Starting backup schedule ${this.serverSettings.backupSchedule}`)
this.scheduleCron()
} else if (this.serverSettings.backupSchedule) {
Logger.info(`[BackupManager] Restarting backup schedule ${this.serverSettings.backupSchedule}`)
if (this.scheduleTask.destroy) this.scheduleTask.destroy()
this.scheduleCron()
}
}

View file

@ -623,6 +623,10 @@ class Audiobook {
return this.book.isSearchMatch(search.toLowerCase().trim())
}
searchQuery(search) {
return this.book.getQueryMatches(search.toLowerCase().trim())
}
getAudioFileByIno(ino) {
return this.audioFiles.find(af => af.ino === ino)
}

View file

@ -5,7 +5,6 @@ const parseAuthors = require('../utils/parseAuthors')
class Book {
constructor(book = null) {
this.olid = null
this.title = null
this.subtitle = null
this.author = null
@ -46,7 +45,6 @@ class Book {
}
construct(book) {
this.olid = book.olid
this.title = book.title
this.subtitle = book.subtitle || null
this.author = book.author
@ -69,7 +67,6 @@ class Book {
toJSON() {
return {
olid: this.olid,
title: this.title,
subtitle: this.subtitle,
author: this.author,
@ -111,7 +108,6 @@ class Book {
}
setData(data) {
this.olid = data.olid || null
this.title = data.title || null
this.subtitle = data.subtitle || null
this.author = data.author || null
@ -217,6 +213,17 @@ class Book {
return this._title.toLowerCase().includes(search) || this._subtitle.toLowerCase().includes(search) || this._author.toLowerCase().includes(search) || this._series.toLowerCase().includes(search)
}
getQueryMatches(search) {
var titleMatch = this._title.toLowerCase().includes(search) || this._subtitle.toLowerCase().includes(search)
var authorMatch = this._author.toLowerCase().includes(search)
var seriesMatch = this._series.toLowerCase().includes(search)
return {
book: titleMatch ? 'title' : authorMatch ? 'author' : seriesMatch ? 'series' : false,
author: authorMatch ? this._author : false,
series: seriesMatch ? this._series : false
}
}
setDetailsFromFileMetadata(audioFileMetadata) {
const MetadataMapArray = [
{

View file

@ -5,6 +5,7 @@ class Library {
this.id = null
this.name = null
this.folders = []
this.icon = 'database'
this.lastScan = 0
@ -24,6 +25,8 @@ class Library {
this.id = library.id
this.name = library.name
this.folders = (library.folders || []).map(f => new Folder(f))
this.icon = library.icon || 'database'
this.createdAt = library.createdAt
this.lastUpdate = library.lastUpdate
}
@ -33,6 +36,7 @@ class Library {
id: this.id,
name: this.name,
folders: (this.folders || []).map(f => f.toJSON()),
icon: this.icon,
createdAt: this.createdAt,
lastUpdate: this.lastUpdate
}
@ -55,6 +59,7 @@ class Library {
return newFolder
})
}
this.icon = data.icon || 'database'
this.createdAt = Date.now()
this.lastUpdate = Date.now()
}