mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-26 00:29:53 +01:00
Add api route for changing sorting prefixes, update default sorting prefixes to include a
This commit is contained in:
parent
39b6ede1e9
commit
826963bf00
@ -36,7 +36,10 @@
|
|||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="newServerSettings.sortingIgnorePrefix" class="w-72 ml-14 mb-2">
|
<div v-if="newServerSettings.sortingIgnorePrefix" class="w-72 ml-14 mb-2">
|
||||||
<ui-multi-select v-model="newServerSettings.sortingPrefixes" small :items="newServerSettings.sortingPrefixes" :label="$strings.LabelPrefixesToIgnore" @input="updateSortingPrefixes" :disabled="updatingServerSettings" />
|
<ui-multi-select v-model="newServerSettings.sortingPrefixes" small :items="newServerSettings.sortingPrefixes" :label="$strings.LabelPrefixesToIgnore" @input="sortingPrefixesUpdated" :disabled="savingPrefixes" />
|
||||||
|
<div class="flex justify-end py-1">
|
||||||
|
<ui-btn v-if="hasPrefixesChanged" color="success" :loading="savingPrefixes" small @click="updateSortingPrefixes">Save</ui-btn>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center py-2 mb-2">
|
<div class="flex items-center py-2 mb-2">
|
||||||
@ -260,8 +263,10 @@ export default {
|
|||||||
homepageUseBookshelfView: false,
|
homepageUseBookshelfView: false,
|
||||||
useBookshelfView: false,
|
useBookshelfView: false,
|
||||||
isPurgingCache: false,
|
isPurgingCache: false,
|
||||||
|
hasPrefixesChanged: false,
|
||||||
newServerSettings: {},
|
newServerSettings: {},
|
||||||
showConfirmPurgeCache: false,
|
showConfirmPurgeCache: false,
|
||||||
|
savingPrefixes: false,
|
||||||
metadataFileFormats: [
|
metadataFileFormats: [
|
||||||
{
|
{
|
||||||
text: '.json',
|
text: '.json',
|
||||||
@ -304,14 +309,35 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateSortingPrefixes(val) {
|
sortingPrefixesUpdated(val) {
|
||||||
if (!val || !val.length) {
|
const prefixes = [...new Set(val?.map((prefix) => prefix.trim().toLowerCase()) || [])]
|
||||||
|
this.newServerSettings.sortingPrefixes = prefixes
|
||||||
|
const serverPrefixes = this.serverSettings.sortingPrefixes || []
|
||||||
|
this.hasPrefixesChanged = prefixes.some((p) => !serverPrefixes.includes(p)) || serverPrefixes.some((p) => !prefixes.includes(p))
|
||||||
|
},
|
||||||
|
updateSortingPrefixes() {
|
||||||
|
const prefixes = [...new Set(this.newServerSettings.sortingPrefixes.map((prefix) => prefix.trim().toLowerCase()) || [])]
|
||||||
|
if (!prefixes.length) {
|
||||||
this.$toast.error('Must have at least 1 prefix')
|
this.$toast.error('Must have at least 1 prefix')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var prefixes = val.map((prefix) => prefix.trim().toLowerCase())
|
|
||||||
this.updateServerSettings({
|
this.savingPrefixes = true
|
||||||
sortingPrefixes: prefixes
|
this.$axios
|
||||||
|
.$patch(`/api/sorting-prefixes`, { sortingPrefixes: prefixes })
|
||||||
|
.then((data) => {
|
||||||
|
this.$toast.success(`Sorting prefixes updated. ${data.rowsUpdated} rows`)
|
||||||
|
if (data.serverSettings) {
|
||||||
|
this.$store.commit('setServerSettings', data.serverSettings)
|
||||||
|
}
|
||||||
|
this.hasPrefixesChanged = false
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Failed to update prefixes', error)
|
||||||
|
this.$toast.error('Failed to update sorting prefixes')
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.savingPrefixes = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateScannerCoverProvider(val) {
|
updateScannerCoverProvider(val) {
|
||||||
|
@ -7,7 +7,7 @@ const Database = require('../Database')
|
|||||||
|
|
||||||
const libraryItemFilters = require('../utils/queries/libraryItemFilters')
|
const libraryItemFilters = require('../utils/queries/libraryItemFilters')
|
||||||
const patternValidation = require('../libs/nodeCron/pattern-validation')
|
const patternValidation = require('../libs/nodeCron/pattern-validation')
|
||||||
const { isObject } = require('../utils/index')
|
const { isObject, getTitleIgnorePrefix } = require('../utils/index')
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is a controller for routes that don't have a home yet :(
|
// This is a controller for routes that don't have a home yet :(
|
||||||
@ -127,7 +127,7 @@ class MiscController {
|
|||||||
}
|
}
|
||||||
const settingsUpdate = req.body
|
const settingsUpdate = req.body
|
||||||
if (!settingsUpdate || !isObject(settingsUpdate)) {
|
if (!settingsUpdate || !isObject(settingsUpdate)) {
|
||||||
return res.status(500).send('Invalid settings update object')
|
return res.status(400).send('Invalid settings update object')
|
||||||
}
|
}
|
||||||
|
|
||||||
const madeUpdates = Database.serverSettings.update(settingsUpdate)
|
const madeUpdates = Database.serverSettings.update(settingsUpdate)
|
||||||
@ -145,6 +145,103 @@ class MiscController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PATCH: /api/sorting-prefixes
|
||||||
|
*
|
||||||
|
* @param {import('express').Request} req
|
||||||
|
* @param {import('express').Response} res
|
||||||
|
*/
|
||||||
|
async updateSortingPrefixes(req, res) {
|
||||||
|
if (!req.user.isAdminOrUp) {
|
||||||
|
Logger.error('User other than admin attempting to update server sorting prefixes', req.user)
|
||||||
|
return res.sendStatus(403)
|
||||||
|
}
|
||||||
|
let sortingPrefixes = req.body.sortingPrefixes
|
||||||
|
if (!sortingPrefixes?.length || !Array.isArray(sortingPrefixes)) {
|
||||||
|
return res.status(400).send('Invalid request body')
|
||||||
|
}
|
||||||
|
sortingPrefixes = [...new Set(sortingPrefixes.map(p => p?.trim?.().toLowerCase()).filter(p => p))]
|
||||||
|
if (!sortingPrefixes.length) {
|
||||||
|
return res.status(400).send('Invalid sortingPrefixes in request body')
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.debug(`[MiscController] Updating sorting prefixes ${sortingPrefixes.join(', ')}`)
|
||||||
|
Database.serverSettings.sortingPrefixes = sortingPrefixes
|
||||||
|
await Database.updateServerSettings()
|
||||||
|
|
||||||
|
let rowsUpdated = 0
|
||||||
|
// Update titleIgnorePrefix column on books
|
||||||
|
const books = await Database.bookModel.findAll({
|
||||||
|
attributes: ['id', 'title', 'titleIgnorePrefix']
|
||||||
|
})
|
||||||
|
const bulkUpdateBooks = []
|
||||||
|
books.forEach((book) => {
|
||||||
|
const titleIgnorePrefix = getTitleIgnorePrefix(book.title)
|
||||||
|
if (titleIgnorePrefix !== book.titleIgnorePrefix) {
|
||||||
|
bulkUpdateBooks.push({
|
||||||
|
id: book.id,
|
||||||
|
titleIgnorePrefix
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (bulkUpdateBooks.length) {
|
||||||
|
Logger.info(`[MiscController] Updating titleIgnorePrefix on ${bulkUpdateBooks.length} books`)
|
||||||
|
rowsUpdated += bulkUpdateBooks.length
|
||||||
|
await Database.bookModel.bulkCreate(bulkUpdateBooks, {
|
||||||
|
updateOnDuplicate: ['titleIgnorePrefix']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update titleIgnorePrefix column on podcasts
|
||||||
|
const podcasts = await Database.podcastModel.findAll({
|
||||||
|
attributes: ['id', 'title', 'titleIgnorePrefix']
|
||||||
|
})
|
||||||
|
const bulkUpdatePodcasts = []
|
||||||
|
podcasts.forEach((podcast) => {
|
||||||
|
const titleIgnorePrefix = getTitleIgnorePrefix(podcast.title)
|
||||||
|
if (titleIgnorePrefix !== podcast.titleIgnorePrefix) {
|
||||||
|
bulkUpdatePodcasts.push({
|
||||||
|
id: podcast.id,
|
||||||
|
titleIgnorePrefix
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (bulkUpdatePodcasts.length) {
|
||||||
|
Logger.info(`[MiscController] Updating titleIgnorePrefix on ${bulkUpdatePodcasts.length} podcasts`)
|
||||||
|
rowsUpdated += bulkUpdatePodcasts.length
|
||||||
|
await Database.podcastModel.bulkCreate(bulkUpdatePodcasts, {
|
||||||
|
updateOnDuplicate: ['titleIgnorePrefix']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update nameIgnorePrefix column on series
|
||||||
|
const allSeries = await Database.seriesModel.findAll({
|
||||||
|
attributes: ['id', 'name', 'nameIgnorePrefix']
|
||||||
|
})
|
||||||
|
const bulkUpdateSeries = []
|
||||||
|
allSeries.forEach((series) => {
|
||||||
|
const nameIgnorePrefix = getTitleIgnorePrefix(series.name)
|
||||||
|
if (nameIgnorePrefix !== series.nameIgnorePrefix) {
|
||||||
|
bulkUpdateSeries.push({
|
||||||
|
id: series.id,
|
||||||
|
nameIgnorePrefix
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (bulkUpdateSeries.length) {
|
||||||
|
Logger.info(`[MiscController] Updating nameIgnorePrefix on ${bulkUpdateSeries.length} series`)
|
||||||
|
rowsUpdated += bulkUpdateSeries.length
|
||||||
|
await Database.seriesModel.bulkCreate(bulkUpdateSeries, {
|
||||||
|
updateOnDuplicate: ['nameIgnorePrefix']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
rowsUpdated,
|
||||||
|
serverSettings: Database.serverSettings.toJSONForBrowser()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST: /api/authorize
|
* POST: /api/authorize
|
||||||
* Used to authorize an API token
|
* Used to authorize an API token
|
||||||
|
@ -43,7 +43,7 @@ class ServerSettings {
|
|||||||
|
|
||||||
// Sorting
|
// Sorting
|
||||||
this.sortingIgnorePrefix = false
|
this.sortingIgnorePrefix = false
|
||||||
this.sortingPrefixes = ['the']
|
this.sortingPrefixes = ['the', 'a']
|
||||||
|
|
||||||
// Misc Flags
|
// Misc Flags
|
||||||
this.chromecastEnabled = false
|
this.chromecastEnabled = false
|
||||||
|
@ -297,6 +297,7 @@ class ApiRouter {
|
|||||||
this.router.post('/upload', MiscController.handleUpload.bind(this))
|
this.router.post('/upload', MiscController.handleUpload.bind(this))
|
||||||
this.router.get('/tasks', MiscController.getTasks.bind(this))
|
this.router.get('/tasks', MiscController.getTasks.bind(this))
|
||||||
this.router.patch('/settings', MiscController.updateServerSettings.bind(this))
|
this.router.patch('/settings', MiscController.updateServerSettings.bind(this))
|
||||||
|
this.router.patch('/sorting-prefixes', MiscController.updateSortingPrefixes.bind(this))
|
||||||
this.router.post('/authorize', MiscController.authorize.bind(this))
|
this.router.post('/authorize', MiscController.authorize.bind(this))
|
||||||
this.router.get('/tags', MiscController.getAllTags.bind(this))
|
this.router.get('/tags', MiscController.getAllTags.bind(this))
|
||||||
this.router.post('/tags/rename', MiscController.renameTag.bind(this))
|
this.router.post('/tags/rename', MiscController.renameTag.bind(this))
|
||||||
|
Loading…
Reference in New Issue
Block a user