Skip to content

Commit

Permalink
feat(webui): make custom author roles consistent
Browse files Browse the repository at this point in the history
  • Loading branch information
noaione committed Nov 12, 2023
1 parent bc49ce4 commit 8ddec39
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 43 deletions.
8 changes: 8 additions & 0 deletions komga-webui/src/components/ReusableDialogs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<edit-books-dialog
v-model="updateBooksDialog"
:books="updateBooks"
:additional-roles="updateBooksAdditionalRoles"
/>

<bulk-edit-books-dialog
Expand All @@ -68,6 +69,7 @@
<edit-oneshot-dialog
v-model="updateOneshotsDialog"
:oneshots="updateOneshots"
:additional-roles="updateOneshotsAdditionalRoles"
/>

<edit-series-dialog
Expand Down Expand Up @@ -240,6 +242,9 @@ export default Vue.extend({
updateBooks(): BookDto | BookDto[] {
return this.$store.state.updateBooks
},
updateBooksAdditionalRoles(): string[] {
return this.$store.state.updateBooksAdditionalRoles
},
// books bulk
updateBulkBooksDialog: {
get(): boolean {
Expand Down Expand Up @@ -278,6 +283,9 @@ export default Vue.extend({
updateOneshots(): Oneshot | Oneshot[] {
return this.$store.state.updateOneshots
},
updateOneshotsAdditionalRoles(): string[] {
return this.$store.state.updateOneshotsAdditionalRoles
},
// series
updateSeriesDialog: {
get(): boolean {
Expand Down
7 changes: 6 additions & 1 deletion komga-webui/src/components/dialogs/EditBooksDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,11 @@ export default Vue.extend({
type: [Object as () => BookDto, Array as () => BookDto[]],
required: true,
},
additionalRoles: {
type: Array as () => string[],
required: false,
default: () => [],
},
},
watch: {
value(val) {
Expand Down Expand Up @@ -548,7 +553,7 @@ export default Vue.extend({
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
else if (this.books?.metadata?.authors)
remoteRoles = this.books.metadata.authors.map(a => a.role)
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles])
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles, ...this.additionalRoles])
return allRoles.map((role: string) => ({
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
value: role,
Expand Down
8 changes: 7 additions & 1 deletion komga-webui/src/components/dialogs/EditOneshotDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ export default Vue.extend({
genresAvailable: [] as string[],
tagsAvailable: [] as string[],
sharingLabelsAvailable: [] as string[],
isMultiBookAuthorDirty: false, // workaround for author consistency in bulk mode
}
},
props: {
Expand All @@ -652,6 +653,11 @@ export default Vue.extend({
type: [Object as () => Oneshot, Array as () => Oneshot[]],
required: true,
},
additionalRoles: {
type: Array as () => string[],
required: false,
default: () => [],
},
},
watch: {
value(val) {
Expand Down Expand Up @@ -729,7 +735,7 @@ export default Vue.extend({
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
else if (this.books?.metadata?.authors)
remoteRoles = this.books.metadata.authors.map(a => a.role)
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles])
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles, ...this.additionalRoles])
return allRoles.map((role: string) => ({
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
value: role,
Expand Down
14 changes: 14 additions & 0 deletions komga-webui/src/functions/author-roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {authorRoles} from '@/types/author-roles'
import {BookDto} from '@/types/komga-books'

export function getCustomRoles(books: BookDto[]): string[] {
return books.flatMap((b) => b.metadata.authors.map((a) => a.role)).filter((ra) => !authorRoles.includes(ra))
}

export function getCustomRolesForSeries(books: BookDto[], seriesId: string): string[] {
return getCustomRoles(books.filter((b) => b.seriesId === seriesId))
}

export function isAllSelectedSameSeries(books: BookDto[]): boolean {
return books.every((b) => b.seriesId === books[0].seriesId)
}
14 changes: 12 additions & 2 deletions komga-webui/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ export default new Vuex.Store({
updateBooksDialog: false,
deleteBooks: {} as BookDto | BookDto[],
deleteBookDialog: false,
updateBooksAdditionalRoles: [] as string[],
// books bulk
updateBulkBooks: [] as BookDto[],
updateBulkBooksDialog: false,

// oneshots
updateOneshots: {} as Oneshot | Oneshot[],
updateOneshotsDialog: false,
updateOneshotsAdditionalRoles: [] as string[],

// series
updateSeries: {} as SeriesDto | SeriesDto[],
Expand Down Expand Up @@ -134,6 +136,9 @@ export default new Vuex.Store({
setUpdateBulkBooks(state, books) {
state.updateBulkBooks = books
},
setUpdateBooksAdditionalRoles(state, roles) {
state.updateBooksAdditionalRoles = roles
},
setUpdateBulkBooksDialog(state, dialog) {
state.updateBulkBooksDialog = dialog
},
Expand All @@ -144,6 +149,9 @@ export default new Vuex.Store({
setUpdateOneshotsDialog(state, dialog) {
state.updateOneshotsDialog = dialog
},
setUpdateOneshotsAdditionalRoles(state, roles) {
state.updateOneshotsAdditionalRoles = roles
},
// Series
setUpdateSeries(state, series) {
state.updateSeries = series
Expand Down Expand Up @@ -229,8 +237,9 @@ export default new Vuex.Store({
commit('setDeleteLibraryDialog', value)
},
// books
dialogUpdateBooks({commit}, books) {
dialogUpdateBooks({commit}, {books, roles}) {
commit('setUpdateBooks', books)
commit('setUpdateBooksAdditionalRoles', roles || [])
commit('setUpdateBooksDialog', true)
},
dialogUpdateBooksDisplay({commit}, value) {
Expand All @@ -252,8 +261,9 @@ export default new Vuex.Store({
commit('setUpdateBulkBooksDialog', value)
},
// oneshots
dialogUpdateOneshots({commit}, oneshots) {
dialogUpdateOneshots({commit}, {oneshots, roles}) {
commit('setUpdateOneshots', oneshots)
commit('setUpdateOneshotsAdditionalRoles', roles || [])
commit('setUpdateOneshotsDialog', true)
},
dialogUpdateOneshotsDisplay({commit}, value) {
Expand Down
4 changes: 3 additions & 1 deletion komga-webui/src/views/BrowseBook.vue
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@
import BookActionsMenu from '@/components/menus/BookActionsMenu.vue'
import ItemCard from '@/components/ItemCard.vue'
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
import {getCustomRoles} from '@/functions/author-roles'
import {groupAuthorsByRole} from '@/functions/authors'
import {getBookFormatFromMediaType} from '@/functions/book-format'
import {getPagesLeft, getReadProgress, getReadProgressPercentage} from '@/functions/book-progress'
Expand Down Expand Up @@ -645,7 +646,8 @@ export default Vue.extend({
this.$komgaBooks.refreshMetadata(this.book)
},
editBook() {
this.$store.dispatch('dialogUpdateBooks', this.book)
const customRole = getCustomRoles(this.siblings)
this.$store.dispatch('dialogUpdateBooks', {books: this.book, roles: customRole})
},
},
})
Expand Down
6 changes: 4 additions & 2 deletions komga-webui/src/views/BrowseCollection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ import MultiSelectBar from '@/components/bars/MultiSelectBar.vue'
import {LIBRARIES_ALL} from '@/types/library'
import {ReadStatus} from '@/types/enum-books'
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
import {getCustomRoles} from '@/functions/author-roles'
import {mergeFilterParams, toNameValue} from '@/functions/filter'
import FilterDrawer from '@/components/FilterDrawer.vue'
import FilterPanels from '@/components/FilterPanels.vue'
Expand Down Expand Up @@ -493,15 +494,16 @@ export default Vue.extend({
async editSingleSeries(series: SeriesDto) {
if (series.oneshot) {
const book = (await this.$komgaSeries.getBooks(series.id)).content[0]
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
} else
this.$store.dispatch('dialogUpdateSeries', series)
},
async editMultipleSeries() {
if (this.selectedSeries.every(s => s.oneshot)) {
const books = await Promise.all(this.selectedSeries.map(s => this.$komgaSeries.getBooks(s.id)))
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
this.$store.dispatch('dialogUpdateOneshots', oneshots)
const customRole = getCustomRoles(oneshots.map(o => o.book))
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
} else
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
},
Expand Down
6 changes: 4 additions & 2 deletions komga-webui/src/views/BrowseLibraries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
import LibraryNavigation from '@/components/LibraryNavigation.vue'
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
import PageSizeSelect from '@/components/PageSizeSelect.vue'
import {getCustomRoles} from '@/functions/author-roles'
import {parseBooleanFilter, parseQuerySort} from '@/functions/query-params'
import {ReadStatus} from '@/types/enum-books'
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
Expand Down Expand Up @@ -589,15 +590,16 @@ export default Vue.extend({
async editSingleSeries(series: SeriesDto) {
if (series.oneshot) {
const book = (await this.$komgaSeries.getBooks(series.id)).content[0]
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
} else
this.$store.dispatch('dialogUpdateSeries', series)
},
async editMultipleSeries() {
if (this.selectedOneshots) {
const books = await Promise.all(this.selectedSeries.map(s => this.$komgaSeries.getBooks(s.id)))
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
this.$store.dispatch('dialogUpdateOneshots', oneshots)
const customRole = getCustomRoles(oneshots.map(o => o.book))
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
} else
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
},
Expand Down
3 changes: 2 additions & 1 deletion komga-webui/src/views/BrowseOneshot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,8 @@ export default Vue.extend({
this.$komgaBooks.refreshMetadata(this.book)
},
editBook() {
this.$store.dispatch('dialogUpdateOneshots', {series: this.series, book: this.book} as Oneshot)
const oneshots = {series: this.series, book: this.book} as Oneshot
this.$store.dispatch('dialogUpdateOneshots', {oneshots})
},
},
})
Expand Down
20 changes: 6 additions & 14 deletions komga-webui/src/views/BrowseReadList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ import FilterList from '@/components/FilterList.vue'
import {ReadStatus} from '@/types/enum-books'
import {authorRoles} from '@/types/author-roles'
import {LibraryDto} from '@/types/komga-libraries'
import {isAllSelectedSameSeries, getCustomRolesForSeries} from '@/functions/author-roles'
import {mergeFilterParams, toNameValue} from '@/functions/filter'
import {Location} from 'vue-router'
import {readListFileUrl} from '@/functions/urls'
Expand Down Expand Up @@ -478,20 +479,11 @@ export default Vue.extend({
reloadPage: throttle(function (this: any) {
this.loadPage(this.readListId, this.page)
}, 1000),
async editSingleBook(book: BookDto) {
if (book.oneshot) {
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
} else
this.$store.dispatch('dialogUpdateBooks', book)
},
async editMultipleBooks() {
if (this.selectedBooks.every(b => b.oneshot)) {
const series = await Promise.all(this.selectedBooks.map(b => this.$komgaSeries.getOneSeries(b.seriesId)))
const oneshots = this.selectedBooks.map((b, index) => ({series: series[index], book: b} as Oneshot))
this.$store.dispatch('dialogUpdateOneshots', oneshots)
} else
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
editSingleBook(book: BookDto) {
this.$store.dispatch('dialogUpdateBooks', book)
},
editMultipleBooks() {
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
},
bulkEditMultipleBooks() {
this.$store.dispatch('dialogUpdateBulkBooks', this.selectedBooks)
Expand Down
7 changes: 5 additions & 2 deletions komga-webui/src/views/BrowseSeries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
import ItemCard from '@/components/ItemCard.vue'
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
import PageSizeSelect from '@/components/PageSizeSelect.vue'
import {getCustomRoles} from '@/functions/author-roles'
import {parseQuerySort} from '@/functions/query-params'
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
import {ReadStatus} from '@/types/enum-books'
Expand Down Expand Up @@ -911,10 +912,12 @@ export default Vue.extend({
this.$store.dispatch('dialogUpdateSeries', this.series)
},
editSingleBook(book: BookDto) {
this.$store.dispatch('dialogUpdateBooks', book)
const customRoles = getCustomRoles(this.books)
this.$store.dispatch('dialogUpdateBooks', {books: book, roles: customRoles})
},
editMultipleBooks() {
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
const customRoles = getCustomRoles(this.books)
this.$store.dispatch('dialogUpdateBooks', {books: this.selectedBooks, roles: customRoles})
},
bulkEditMultipleBooks() {
this.$store.dispatch('dialogUpdateBulkBooks', this.$_.sortBy(this.selectedBooks, ['metadata.numberSort']))
Expand Down
38 changes: 29 additions & 9 deletions komga-webui/src/views/DashboardView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ import {BookSseDto, ReadProgressSeriesSseDto, ReadProgressSseDto, SeriesSseDto}
import {LibraryDto} from '@/types/komga-libraries'
import {PageLoader} from '@/types/pageLoader'
import {ItemContext} from '@/types/items'
import {getCustomRoles, getCustomRolesForSeries, isAllSelectedSameSeries} from '@/functions/author-roles'
export default Vue.extend({
name: 'DashboardView',
Expand Down Expand Up @@ -430,16 +431,19 @@ export default Vue.extend({
async singleEditSeries(series: SeriesDto) {
if (series.oneshot) {
let book = (await this.$komgaSeries.getBooks(series.id)).content[0]
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
} else
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
} else {
this.$store.dispatch('dialogUpdateSeries', series)
}
},
async singleEditBook(book: BookDto) {
if (book.oneshot) {
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
} else
this.$store.dispatch('dialogUpdateBooks', book)
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
} else {
const customRoles = getCustomRolesForSeries(this.getAllBooksFromLoader(), book.seriesId)
this.$store.dispatch('dialogUpdateBooks', {books: book, roles: customRoles})
}
},
async markSelectedSeriesRead() {
await Promise.all(this.selectedSeries.map(s =>
Expand All @@ -465,17 +469,24 @@ export default Vue.extend({
if (this.selectedSeries.every(s => s.oneshot)) {
const books = await Promise.all(this.selectedSeries.map(s => this.$komgaSeries.getBooks(s.id)))
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
this.$store.dispatch('dialogUpdateOneshots', oneshots)
const customRole = getCustomRoles(oneshots.map(o => o.book))
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
} else
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
},
async editMultipleBooks() {
if (this.selectedBooks.every(b => b.oneshot)) {
const series = await Promise.all(this.selectedBooks.map(b => this.$komgaSeries.getOneSeries(b.seriesId)))
const oneshots = this.selectedBooks.map((b, index) => ({series: series[index], book: b} as Oneshot))
this.$store.dispatch('dialogUpdateOneshots', oneshots)
} else
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
const customRole = getCustomRoles(oneshots.map(o => o.book))
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
} else {
let customRoles = [] as string[]
if (isAllSelectedSameSeries(this.selectedBooks)) {
customRoles = getCustomRolesForSeries(this.getAllBooksFromLoader(), this.selectedBooks[0].seriesId)
}
this.$store.dispatch('dialogUpdateBooks', {books: this.selectedBooks, roles: customRoles})
}
},
deleteSeries() {
this.$store.dispatch('dialogDeleteSeries', this.selectedSeries)
Expand Down Expand Up @@ -509,6 +520,15 @@ export default Vue.extend({
return undefined
}
},
getAllBooksFromLoader(): BookDto[] {
return [
...(this.loaderInProgressBooks?.items || []),
...(this.loaderOnDeckBooks?.items || []),
...(this.loaderRecentlyReleasedBooks?.items || []),
...(this.loaderLatestBooks?.items || []),
...(this.loaderRecentlyReadBooks?.items || []),
]
},
},
})
</script>
Expand Down
Loading

0 comments on commit 8ddec39

Please sign in to comment.