Skip to content

Commit 7ad106e

Browse files
committed
feat(webui): make custom author roles consistent
fix(webui): add additionalRoles to authorRoles result
1 parent 72cf68b commit 7ad106e

File tree

13 files changed

+119
-44
lines changed

13 files changed

+119
-44
lines changed

komga-webui/src/components/ReusableDialogs.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
<edit-books-dialog
5959
v-model="updateBooksDialog"
6060
:books="updateBooks"
61+
:additional-roles="updateBooksAdditionalRoles"
6162
/>
6263

6364
<bulk-edit-books-dialog
@@ -68,6 +69,7 @@
6869
<edit-oneshot-dialog
6970
v-model="updateOneshotsDialog"
7071
:oneshots="updateOneshots"
72+
:additional-roles="updateOneshotsAdditionalRoles"
7173
/>
7274

7375
<edit-series-dialog
@@ -240,6 +242,9 @@ export default Vue.extend({
240242
updateBooks(): BookDto | BookDto[] {
241243
return this.$store.state.updateBooks
242244
},
245+
updateBooksAdditionalRoles(): string[] {
246+
return this.$store.state.updateBooksAdditionalRoles
247+
},
243248
// books bulk
244249
updateBulkBooksDialog: {
245250
get(): boolean {
@@ -278,6 +283,9 @@ export default Vue.extend({
278283
updateOneshots(): Oneshot | Oneshot[] {
279284
return this.$store.state.updateOneshots
280285
},
286+
updateOneshotsAdditionalRoles(): string[] {
287+
return this.$store.state.updateOneshotsAdditionalRoles
288+
},
281289
// series
282290
updateSeriesDialog: {
283291
get(): boolean {

komga-webui/src/components/dialogs/EditBooksDialog.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,11 @@ export default Vue.extend({
489489
type: [Object as () => BookDto, Array as () => BookDto[]],
490490
required: true,
491491
},
492+
additionalRoles: {
493+
type: Array as () => string[],
494+
required: false,
495+
default: () => [],
496+
},
492497
},
493498
watch: {
494499
value(val) {
@@ -548,7 +553,7 @@ export default Vue.extend({
548553
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
549554
else if (this.books?.metadata?.authors)
550555
remoteRoles = this.books.metadata.authors.map(a => a.role)
551-
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles])
556+
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles, ...this.additionalRoles])
552557
return allRoles.map((role: string) => ({
553558
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
554559
value: role,

komga-webui/src/components/dialogs/EditOneshotDialog.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ export default Vue.extend({
644644
genresAvailable: [] as string[],
645645
tagsAvailable: [] as string[],
646646
sharingLabelsAvailable: [] as string[],
647+
isMultiBookAuthorDirty: false, // workaround for author consistency in bulk mode
647648
}
648649
},
649650
props: {
@@ -652,6 +653,11 @@ export default Vue.extend({
652653
type: [Object as () => Oneshot, Array as () => Oneshot[]],
653654
required: true,
654655
},
656+
additionalRoles: {
657+
type: Array as () => string[],
658+
required: false,
659+
default: () => [],
660+
},
655661
},
656662
watch: {
657663
value(val) {
@@ -729,7 +735,7 @@ export default Vue.extend({
729735
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
730736
else if (this.books?.metadata?.authors)
731737
remoteRoles = this.books.metadata.authors.map(a => a.role)
732-
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles])
738+
const allRoles = this.$_.uniq([...authorRoles, ...remoteRoles, ...this.customRoles, ...this.additionalRoles])
733739
return allRoles.map((role: string) => ({
734740
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
735741
value: role,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {authorRoles} from '@/types/author-roles'
2+
import {BookDto} from '@/types/komga-books'
3+
4+
export function getCustomRoles(books: BookDto[]): string[] {
5+
return books.flatMap((b) => b.metadata.authors.map((a) => a.role)).filter((ra) => !authorRoles.includes(ra))
6+
}
7+
8+
export function getCustomRolesForSeries(books: BookDto[], seriesId: string): string[] {
9+
return getCustomRoles(books.filter((b) => b.seriesId === seriesId))
10+
}
11+
12+
export function isAllSelectedSameSeries(books: BookDto[]): boolean {
13+
return books.every((b) => b.seriesId === books[0].seriesId)
14+
}

komga-webui/src/store.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ export default new Vuex.Store({
4040
updateBooksDialog: false,
4141
deleteBooks: {} as BookDto | BookDto[],
4242
deleteBookDialog: false,
43+
updateBooksAdditionalRoles: [] as string[],
4344
// books bulk
4445
updateBulkBooks: [] as BookDto[],
4546
updateBulkBooksDialog: false,
4647

4748
// oneshots
4849
updateOneshots: {} as Oneshot | Oneshot[],
4950
updateOneshotsDialog: false,
51+
updateOneshotsAdditionalRoles: [] as string[],
5052

5153
// series
5254
updateSeries: {} as SeriesDto | SeriesDto[],
@@ -134,6 +136,9 @@ export default new Vuex.Store({
134136
setUpdateBulkBooks(state, books) {
135137
state.updateBulkBooks = books
136138
},
139+
setUpdateBooksAdditionalRoles(state, roles) {
140+
state.updateBooksAdditionalRoles = roles
141+
},
137142
setUpdateBulkBooksDialog(state, dialog) {
138143
state.updateBulkBooksDialog = dialog
139144
},
@@ -144,6 +149,9 @@ export default new Vuex.Store({
144149
setUpdateOneshotsDialog(state, dialog) {
145150
state.updateOneshotsDialog = dialog
146151
},
152+
setUpdateOneshotsAdditionalRoles(state, roles) {
153+
state.updateOneshotsAdditionalRoles = roles
154+
},
147155
// Series
148156
setUpdateSeries(state, series) {
149157
state.updateSeries = series
@@ -229,8 +237,9 @@ export default new Vuex.Store({
229237
commit('setDeleteLibraryDialog', value)
230238
},
231239
// books
232-
dialogUpdateBooks({commit}, books) {
240+
dialogUpdateBooks({commit}, {books, roles}) {
233241
commit('setUpdateBooks', books)
242+
commit('setUpdateBooksAdditionalRoles', roles || [])
234243
commit('setUpdateBooksDialog', true)
235244
},
236245
dialogUpdateBooksDisplay({commit}, value) {
@@ -252,8 +261,9 @@ export default new Vuex.Store({
252261
commit('setUpdateBulkBooksDialog', value)
253262
},
254263
// oneshots
255-
dialogUpdateOneshots({commit}, oneshots) {
264+
dialogUpdateOneshots({commit}, {oneshots, roles}) {
256265
commit('setUpdateOneshots', oneshots)
266+
commit('setUpdateOneshotsAdditionalRoles', roles || [])
257267
commit('setUpdateOneshotsDialog', true)
258268
},
259269
dialogUpdateOneshotsDisplay({commit}, value) {

komga-webui/src/views/BrowseBook.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@
408408
import BookActionsMenu from '@/components/menus/BookActionsMenu.vue'
409409
import ItemCard from '@/components/ItemCard.vue'
410410
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
411+
import {getCustomRoles} from '@/functions/author-roles'
411412
import {groupAuthorsByRole} from '@/functions/authors'
412413
import {getBookFormatFromMediaType} from '@/functions/book-format'
413414
import {getPagesLeft, getReadProgress, getReadProgressPercentage} from '@/functions/book-progress'
@@ -645,7 +646,8 @@ export default Vue.extend({
645646
this.$komgaBooks.refreshMetadata(this.book)
646647
},
647648
editBook() {
648-
this.$store.dispatch('dialogUpdateBooks', this.book)
649+
const customRole = getCustomRoles(this.siblings)
650+
this.$store.dispatch('dialogUpdateBooks', {books: this.book, roles: customRole})
649651
},
650652
},
651653
})

komga-webui/src/views/BrowseCollection.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ import MultiSelectBar from '@/components/bars/MultiSelectBar.vue'
150150
import {LIBRARIES_ALL} from '@/types/library'
151151
import {ReadStatus} from '@/types/enum-books'
152152
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
153+
import {getCustomRoles} from '@/functions/author-roles'
153154
import {mergeFilterParams, toNameValue} from '@/functions/filter'
154155
import FilterDrawer from '@/components/FilterDrawer.vue'
155156
import FilterPanels from '@/components/FilterPanels.vue'
@@ -493,15 +494,16 @@ export default Vue.extend({
493494
async editSingleSeries(series: SeriesDto) {
494495
if (series.oneshot) {
495496
const book = (await this.$komgaSeries.getBooks(series.id)).content[0]
496-
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
497+
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
497498
} else
498499
this.$store.dispatch('dialogUpdateSeries', series)
499500
},
500501
async editMultipleSeries() {
501502
if (this.selectedSeries.every(s => s.oneshot)) {
502503
const books = await Promise.all(this.selectedSeries.map(s => this.$komgaSeries.getBooks(s.id)))
503-
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
504-
this.$store.dispatch('dialogUpdateOneshots', oneshots)
504+
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))]
505+
const customRole = getCustomRoles(oneshots.map(o => o.book))
506+
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
505507
} else
506508
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
507509
},

komga-webui/src/views/BrowseLibraries.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
131131
import LibraryNavigation from '@/components/LibraryNavigation.vue'
132132
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
133133
import PageSizeSelect from '@/components/PageSizeSelect.vue'
134+
import {getCustomRoles} from '@/functions/author-roles'
134135
import {parseBooleanFilter, parseQuerySort} from '@/functions/query-params'
135136
import {ReadStatus} from '@/types/enum-books'
136137
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
@@ -589,15 +590,16 @@ export default Vue.extend({
589590
async editSingleSeries(series: SeriesDto) {
590591
if (series.oneshot) {
591592
const book = (await this.$komgaSeries.getBooks(series.id)).content[0]
592-
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
593+
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
593594
} else
594595
this.$store.dispatch('dialogUpdateSeries', series)
595596
},
596597
async editMultipleSeries() {
597598
if (this.selectedOneshots) {
598599
const books = await Promise.all(this.selectedSeries.map(s => this.$komgaSeries.getBooks(s.id)))
599600
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
600-
this.$store.dispatch('dialogUpdateOneshots', oneshots)
601+
const customRole = getCustomRoles(oneshots.map(o => o.book))
602+
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
601603
} else
602604
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
603605
},

komga-webui/src/views/BrowseOneshot.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,8 @@ export default Vue.extend({
781781
this.$komgaBooks.refreshMetadata(this.book)
782782
},
783783
editBook() {
784-
this.$store.dispatch('dialogUpdateOneshots', {series: this.series, book: this.book} as Oneshot)
784+
const oneshots = {series: this.series, book: this.book} as Oneshot
785+
this.$store.dispatch('dialogUpdateOneshots', {oneshots})
785786
},
786787
},
787788
})

komga-webui/src/views/BrowseReadList.vue

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ import FilterList from '@/components/FilterList.vue'
181181
import {ReadStatus} from '@/types/enum-books'
182182
import {authorRoles} from '@/types/author-roles'
183183
import {LibraryDto} from '@/types/komga-libraries'
184+
import {isAllSelectedSameSeries, getCustomRolesForSeries} from '@/functions/author-roles'
184185
import {mergeFilterParams, toNameValue} from '@/functions/filter'
185186
import {Location} from 'vue-router'
186187
import {readListFileUrl} from '@/functions/urls'
@@ -478,20 +479,11 @@ export default Vue.extend({
478479
reloadPage: throttle(function (this: any) {
479480
this.loadPage(this.readListId, this.page)
480481
}, 1000),
481-
async editSingleBook(book: BookDto) {
482-
if (book.oneshot) {
483-
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
484-
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
485-
} else
486-
this.$store.dispatch('dialogUpdateBooks', book)
487-
},
488-
async editMultipleBooks() {
489-
if (this.selectedBooks.every(b => b.oneshot)) {
490-
const series = await Promise.all(this.selectedBooks.map(b => this.$komgaSeries.getOneSeries(b.seriesId)))
491-
const oneshots = this.selectedBooks.map((b, index) => ({series: series[index], book: b} as Oneshot))
492-
this.$store.dispatch('dialogUpdateOneshots', oneshots)
493-
} else
494-
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
482+
editSingleBook(book: BookDto) {
483+
this.$store.dispatch('dialogUpdateBooks', book)
484+
},
485+
editMultipleBooks() {
486+
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
495487
},
496488
bulkEditMultipleBooks() {
497489
this.$store.dispatch('dialogUpdateBulkBooks', this.selectedBooks)

0 commit comments

Comments
 (0)