mirror of
https://github.com/gotson/komga.git
synced 2025-12-15 21:12:27 +01:00
Merge 20fad2503c into 361d20df2c
This commit is contained in:
commit
9610869091
14 changed files with 122 additions and 36 deletions
|
|
@ -58,6 +58,7 @@
|
||||||
<edit-books-dialog
|
<edit-books-dialog
|
||||||
v-model="updateBooksDialog"
|
v-model="updateBooksDialog"
|
||||||
:books="updateBooks"
|
:books="updateBooks"
|
||||||
|
:additional-roles="updateBooksAdditionalRoles"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<bulk-edit-books-dialog
|
<bulk-edit-books-dialog
|
||||||
|
|
@ -68,6 +69,7 @@
|
||||||
<edit-oneshot-dialog
|
<edit-oneshot-dialog
|
||||||
v-model="updateOneshotsDialog"
|
v-model="updateOneshotsDialog"
|
||||||
:oneshots="updateOneshots"
|
:oneshots="updateOneshots"
|
||||||
|
:additional-roles="updateOneshotsAdditionalRoles"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<edit-series-dialog
|
<edit-series-dialog
|
||||||
|
|
@ -240,6 +242,9 @@ export default Vue.extend({
|
||||||
updateBooks(): BookDto | BookDto[] {
|
updateBooks(): BookDto | BookDto[] {
|
||||||
return this.$store.state.updateBooks
|
return this.$store.state.updateBooks
|
||||||
},
|
},
|
||||||
|
updateBooksAdditionalRoles(): string[] {
|
||||||
|
return this.$store.state.updateBooksAdditionalRoles
|
||||||
|
},
|
||||||
// books bulk
|
// books bulk
|
||||||
updateBulkBooksDialog: {
|
updateBulkBooksDialog: {
|
||||||
get(): boolean {
|
get(): boolean {
|
||||||
|
|
@ -278,6 +283,9 @@ export default Vue.extend({
|
||||||
updateOneshots(): Oneshot | Oneshot[] {
|
updateOneshots(): Oneshot | Oneshot[] {
|
||||||
return this.$store.state.updateOneshots
|
return this.$store.state.updateOneshots
|
||||||
},
|
},
|
||||||
|
updateOneshotsAdditionalRoles(): string[] {
|
||||||
|
return this.$store.state.updateOneshotsAdditionalRoles
|
||||||
|
},
|
||||||
// series
|
// series
|
||||||
updateSeriesDialog: {
|
updateSeriesDialog: {
|
||||||
get(): boolean {
|
get(): boolean {
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,11 @@ export default Vue.extend({
|
||||||
type: [Object as () => BookDto, Array as () => BookDto[]],
|
type: [Object as () => BookDto, Array as () => BookDto[]],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
additionalRoles: {
|
||||||
|
type: Array as () => string[],
|
||||||
|
required: false,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(val) {
|
value(val) {
|
||||||
|
|
@ -549,7 +554,7 @@ export default Vue.extend({
|
||||||
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
|
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
|
||||||
else if (this.books?.metadata?.authors)
|
else if (this.books?.metadata?.authors)
|
||||||
remoteRoles = this.books.metadata.authors.map(a => a.role)
|
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) => ({
|
return allRoles.map((role: string) => ({
|
||||||
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
|
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
|
||||||
value: role,
|
value: role,
|
||||||
|
|
|
||||||
|
|
@ -644,6 +644,7 @@ export default Vue.extend({
|
||||||
genresAvailable: [] as string[],
|
genresAvailable: [] as string[],
|
||||||
tagsAvailable: [] as string[],
|
tagsAvailable: [] as string[],
|
||||||
sharingLabelsAvailable: [] as string[],
|
sharingLabelsAvailable: [] as string[],
|
||||||
|
isMultiBookAuthorDirty: false, // workaround for author consistency in bulk mode
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -652,6 +653,11 @@ export default Vue.extend({
|
||||||
type: [Object as () => Oneshot, Array as () => Oneshot[]],
|
type: [Object as () => Oneshot, Array as () => Oneshot[]],
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
additionalRoles: {
|
||||||
|
type: Array as () => string[],
|
||||||
|
required: false,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(val) {
|
value(val) {
|
||||||
|
|
@ -729,7 +735,7 @@ export default Vue.extend({
|
||||||
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
|
remoteRoles = this.books.flatMap(b => b.metadata.authors).map(a => a.role)
|
||||||
else if (this.books?.metadata?.authors)
|
else if (this.books?.metadata?.authors)
|
||||||
remoteRoles = this.books.metadata.authors.map(a => a.role)
|
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) => ({
|
return allRoles.map((role: string) => ({
|
||||||
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
|
name: this.$te(`author_roles.${role}`) ? this.$t(`author_roles.${role}`).toString() : role,
|
||||||
value: role,
|
value: role,
|
||||||
|
|
|
||||||
14
komga-webui/src/functions/author-roles.ts
Normal file
14
komga-webui/src/functions/author-roles.ts
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,7 @@ export default new Vuex.Store({
|
||||||
updateBooksDialog: false,
|
updateBooksDialog: false,
|
||||||
deleteBooks: {} as BookDto | BookDto[],
|
deleteBooks: {} as BookDto | BookDto[],
|
||||||
deleteBookDialog: false,
|
deleteBookDialog: false,
|
||||||
|
updateBooksAdditionalRoles: [] as string[],
|
||||||
// books bulk
|
// books bulk
|
||||||
updateBulkBooks: [] as BookDto[],
|
updateBulkBooks: [] as BookDto[],
|
||||||
updateBulkBooksDialog: false,
|
updateBulkBooksDialog: false,
|
||||||
|
|
@ -48,6 +49,7 @@ export default new Vuex.Store({
|
||||||
// oneshots
|
// oneshots
|
||||||
updateOneshots: {} as Oneshot | Oneshot[],
|
updateOneshots: {} as Oneshot | Oneshot[],
|
||||||
updateOneshotsDialog: false,
|
updateOneshotsDialog: false,
|
||||||
|
updateOneshotsAdditionalRoles: [] as string[],
|
||||||
|
|
||||||
// series
|
// series
|
||||||
updateSeries: {} as SeriesDto | SeriesDto[],
|
updateSeries: {} as SeriesDto | SeriesDto[],
|
||||||
|
|
@ -145,6 +147,9 @@ export default new Vuex.Store({
|
||||||
setUpdateBulkBooks(state, books) {
|
setUpdateBulkBooks(state, books) {
|
||||||
state.updateBulkBooks = books
|
state.updateBulkBooks = books
|
||||||
},
|
},
|
||||||
|
setUpdateBooksAdditionalRoles(state, roles) {
|
||||||
|
state.updateBooksAdditionalRoles = roles
|
||||||
|
},
|
||||||
setUpdateBulkBooksDialog(state, dialog) {
|
setUpdateBulkBooksDialog(state, dialog) {
|
||||||
state.updateBulkBooksDialog = dialog
|
state.updateBulkBooksDialog = dialog
|
||||||
},
|
},
|
||||||
|
|
@ -155,6 +160,9 @@ export default new Vuex.Store({
|
||||||
setUpdateOneshotsDialog(state, dialog) {
|
setUpdateOneshotsDialog(state, dialog) {
|
||||||
state.updateOneshotsDialog = dialog
|
state.updateOneshotsDialog = dialog
|
||||||
},
|
},
|
||||||
|
setUpdateOneshotsAdditionalRoles(state, roles) {
|
||||||
|
state.updateOneshotsAdditionalRoles = roles
|
||||||
|
},
|
||||||
// Series
|
// Series
|
||||||
setUpdateSeries(state, series) {
|
setUpdateSeries(state, series) {
|
||||||
state.updateSeries = series
|
state.updateSeries = series
|
||||||
|
|
@ -246,8 +254,9 @@ export default new Vuex.Store({
|
||||||
commit('setDeleteLibraryDialog', value)
|
commit('setDeleteLibraryDialog', value)
|
||||||
},
|
},
|
||||||
// books
|
// books
|
||||||
dialogUpdateBooks({commit}, books) {
|
dialogUpdateBooks({commit}, {books, roles}) {
|
||||||
commit('setUpdateBooks', books)
|
commit('setUpdateBooks', books)
|
||||||
|
commit('setUpdateBooksAdditionalRoles', roles || [])
|
||||||
commit('setUpdateBooksDialog', true)
|
commit('setUpdateBooksDialog', true)
|
||||||
},
|
},
|
||||||
dialogUpdateBooksDisplay({commit}, value) {
|
dialogUpdateBooksDisplay({commit}, value) {
|
||||||
|
|
@ -269,8 +278,9 @@ export default new Vuex.Store({
|
||||||
commit('setUpdateBulkBooksDialog', value)
|
commit('setUpdateBulkBooksDialog', value)
|
||||||
},
|
},
|
||||||
// oneshots
|
// oneshots
|
||||||
dialogUpdateOneshots({commit}, oneshots) {
|
dialogUpdateOneshots({commit}, {oneshots, roles}) {
|
||||||
commit('setUpdateOneshots', oneshots)
|
commit('setUpdateOneshots', oneshots)
|
||||||
|
commit('setUpdateOneshotsAdditionalRoles', roles || [])
|
||||||
commit('setUpdateOneshotsDialog', true)
|
commit('setUpdateOneshotsDialog', true)
|
||||||
},
|
},
|
||||||
dialogUpdateOneshotsDisplay({commit}, value) {
|
dialogUpdateOneshotsDisplay({commit}, value) {
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,7 @@
|
||||||
import BookActionsMenu from '@/components/menus/BookActionsMenu.vue'
|
import BookActionsMenu from '@/components/menus/BookActionsMenu.vue'
|
||||||
import ItemCard from '@/components/ItemCard.vue'
|
import ItemCard from '@/components/ItemCard.vue'
|
||||||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||||
|
import {getCustomRoles} from '@/functions/author-roles'
|
||||||
import {groupAuthorsByRole} from '@/functions/authors'
|
import {groupAuthorsByRole} from '@/functions/authors'
|
||||||
import {getBookFormatFromMedia, getBookReadRouteFromMedia} from '@/functions/book-format'
|
import {getBookFormatFromMedia, getBookReadRouteFromMedia} from '@/functions/book-format'
|
||||||
import {getPagesLeft, getReadProgress, getReadProgressPercentage} from '@/functions/book-progress'
|
import {getPagesLeft, getReadProgress, getReadProgressPercentage} from '@/functions/book-progress'
|
||||||
|
|
@ -689,7 +690,8 @@ export default Vue.extend({
|
||||||
this.$komgaBooks.refreshMetadata(this.book)
|
this.$komgaBooks.refreshMetadata(this.book)
|
||||||
},
|
},
|
||||||
editBook() {
|
editBook() {
|
||||||
this.$store.dispatch('dialogUpdateBooks', this.book)
|
const customRole = getCustomRoles(this.siblings)
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: this.book, roles: customRole})
|
||||||
},
|
},
|
||||||
removeFromReadList(readListId: string) {
|
removeFromReadList(readListId: string) {
|
||||||
const rl = this.readLists.find(x => x.id == readListId)
|
const rl = this.readLists.find(x => x.id == readListId)
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ import {
|
||||||
} from '@/types/komga-search'
|
} from '@/types/komga-search'
|
||||||
import i18n from '@/i18n'
|
import i18n from '@/i18n'
|
||||||
import {objIsEqual} from '@/functions/object'
|
import {objIsEqual} from '@/functions/object'
|
||||||
|
import {getCustomRoles} from '@/functions/author-roles'
|
||||||
import {
|
import {
|
||||||
FILTER_ANY,
|
FILTER_ANY,
|
||||||
FILTER_NONE,
|
FILTER_NONE,
|
||||||
|
|
@ -660,10 +661,11 @@ export default Vue.extend({
|
||||||
this.$store.dispatch('dialogAddBooksToReadList', this.selectedBooks.map(b => b.id))
|
this.$store.dispatch('dialogAddBooksToReadList', this.selectedBooks.map(b => b.id))
|
||||||
},
|
},
|
||||||
editSingleBook(book: BookDto) {
|
editSingleBook(book: BookDto) {
|
||||||
this.$store.dispatch('dialogUpdateBooks', book)
|
this.$store.dispatch('dialogUpdateBooks', {books: book})
|
||||||
},
|
},
|
||||||
editMultipleBooks() {
|
editMultipleBooks() {
|
||||||
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
const customRoles = getCustomRoles(this.selectedBooks)
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: this.selectedBooks, roles: customRoles})
|
||||||
},
|
},
|
||||||
bulkEditMultipleBooks() {
|
bulkEditMultipleBooks() {
|
||||||
this.$store.dispatch('dialogUpdateBulkBooks', this.$_.sortBy(this.selectedBooks, ['metadata.numberSort']))
|
this.$store.dispatch('dialogUpdateBulkBooks', this.$_.sortBy(this.selectedBooks, ['metadata.numberSort']))
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ import MultiSelectBar from '@/components/bars/MultiSelectBar.vue'
|
||||||
import {LIBRARIES_ALL} from '@/types/library'
|
import {LIBRARIES_ALL} from '@/types/library'
|
||||||
import {ReadStatus} from '@/types/enum-books'
|
import {ReadStatus} from '@/types/enum-books'
|
||||||
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
import {SeriesStatus, SeriesStatusKeyValue} from '@/types/enum-series'
|
||||||
|
import {getCustomRoles} from '@/functions/author-roles'
|
||||||
import {mergeFilterParams, toNameValue} from '@/functions/filter'
|
import {mergeFilterParams, toNameValue} from '@/functions/filter'
|
||||||
import FilterDrawer from '@/components/FilterDrawer.vue'
|
import FilterDrawer from '@/components/FilterDrawer.vue'
|
||||||
import FilterPanels from '@/components/FilterPanels.vue'
|
import FilterPanels from '@/components/FilterPanels.vue'
|
||||||
|
|
@ -500,7 +501,7 @@ export default Vue.extend({
|
||||||
const book = (await this.$komgaBooks.getBooksList({
|
const book = (await this.$komgaBooks.getBooksList({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
||||||
} as BookSearch)).content[0]
|
} as BookSearch)).content[0]
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', series)
|
this.$store.dispatch('dialogUpdateSeries', series)
|
||||||
},
|
},
|
||||||
|
|
@ -510,7 +511,8 @@ export default Vue.extend({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
||||||
} as BookSearch)))
|
} as BookSearch)))
|
||||||
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
|
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
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,8 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
import {parseQuerySort} from '@/functions/query-params'
|
import {getCustomRoles} from '@/functions/author-roles'
|
||||||
|
import {parseBooleanFilter, parseQuerySort} from '@/functions/query-params'
|
||||||
import {ReadStatus} from '@/types/enum-books'
|
import {ReadStatus} from '@/types/enum-books'
|
||||||
import {SeriesStatus} from '@/types/enum-series'
|
import {SeriesStatus} from '@/types/enum-series'
|
||||||
import {
|
import {
|
||||||
|
|
@ -873,7 +874,7 @@ export default Vue.extend({
|
||||||
const book = (await this.$komgaBooks.getBooksList({
|
const book = (await this.$komgaBooks.getBooksList({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
||||||
} as BookSearch)).content[0]
|
} as BookSearch)).content[0]
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', series)
|
this.$store.dispatch('dialogUpdateSeries', series)
|
||||||
},
|
},
|
||||||
|
|
@ -883,7 +884,8 @@ export default Vue.extend({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
||||||
} as BookSearch)))
|
} as BookSearch)))
|
||||||
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
|
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
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -848,7 +848,8 @@ export default Vue.extend({
|
||||||
this.$komgaBooks.refreshMetadata(this.book)
|
this.$komgaBooks.refreshMetadata(this.book)
|
||||||
},
|
},
|
||||||
editBook() {
|
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})
|
||||||
},
|
},
|
||||||
removeFromReadList(readListId: string) {
|
removeFromReadList(readListId: string) {
|
||||||
const rl = this.readLists.find(x => x.id == readListId)
|
const rl = this.readLists.find(x => x.id == readListId)
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,7 @@ import FilterList from '@/components/FilterList.vue'
|
||||||
import {ReadStatus} from '@/types/enum-books'
|
import {ReadStatus} from '@/types/enum-books'
|
||||||
import {authorRoles} from '@/types/author-roles'
|
import {authorRoles} from '@/types/author-roles'
|
||||||
import {LibraryDto} from '@/types/komga-libraries'
|
import {LibraryDto} from '@/types/komga-libraries'
|
||||||
|
import {isAllSelectedSameSeries, getCustomRolesForSeries} from '@/functions/author-roles'
|
||||||
import {mergeFilterParams, toNameValue} from '@/functions/filter'
|
import {mergeFilterParams, toNameValue} from '@/functions/filter'
|
||||||
import {Location} from 'vue-router'
|
import {Location} from 'vue-router'
|
||||||
import {readListFileUrl} from '@/functions/urls'
|
import {readListFileUrl} from '@/functions/urls'
|
||||||
|
|
@ -485,17 +486,17 @@ export default Vue.extend({
|
||||||
async editSingleBook(book: BookDto) {
|
async editSingleBook(book: BookDto) {
|
||||||
if (book.oneshot) {
|
if (book.oneshot) {
|
||||||
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
|
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else
|
||||||
this.$store.dispatch('dialogUpdateBooks', book)
|
this.$store.dispatch('dialogUpdateBooks', {books: book})
|
||||||
},
|
},
|
||||||
async editMultipleBooks() {
|
async editMultipleBooks() {
|
||||||
if (this.selectedBooks.every(b => b.oneshot)) {
|
if (this.selectedBooks.every(b => b.oneshot)) {
|
||||||
const series = await Promise.all(this.selectedBooks.map(b => this.$komgaSeries.getOneSeries(b.seriesId)))
|
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))
|
const oneshots = this.selectedBooks.map((b, index) => ({series: series[index], book: b} as Oneshot))
|
||||||
this.$store.dispatch('dialogUpdateOneshots', oneshots)
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots})
|
||||||
} else
|
} else
|
||||||
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
this.$store.dispatch('dialogUpdateBooks', {books: this.selectedBooks})
|
||||||
},
|
},
|
||||||
bulkEditMultipleBooks() {
|
bulkEditMultipleBooks() {
|
||||||
this.$store.dispatch('dialogUpdateBulkBooks', this.selectedBooks)
|
this.$store.dispatch('dialogUpdateBulkBooks', this.selectedBooks)
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import ItemCard from '@/components/ItemCard.vue'
|
import ItemCard from '@/components/ItemCard.vue'
|
||||||
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
|
import SeriesActionsMenu from '@/components/menus/SeriesActionsMenu.vue'
|
||||||
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
import PageSizeSelect from '@/components/PageSizeSelect.vue'
|
||||||
|
import {getCustomRoles} from '@/functions/author-roles'
|
||||||
import {parseQuerySort} from '@/functions/query-params'
|
import {parseQuerySort} from '@/functions/query-params'
|
||||||
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
|
import {seriesFileUrl, seriesThumbnailUrl} from '@/functions/urls'
|
||||||
import {MediaProfile, ReadStatus} from '@/types/enum-books'
|
import {MediaProfile, ReadStatus} from '@/types/enum-books'
|
||||||
|
|
@ -1093,10 +1094,12 @@ export default Vue.extend({
|
||||||
this.$store.dispatch('dialogUpdateSeries', this.series)
|
this.$store.dispatch('dialogUpdateSeries', this.series)
|
||||||
},
|
},
|
||||||
editSingleBook(book: BookDto) {
|
editSingleBook(book: BookDto) {
|
||||||
this.$store.dispatch('dialogUpdateBooks', book)
|
const customRoles = getCustomRoles(this.books)
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: book, roles: customRoles})
|
||||||
},
|
},
|
||||||
editMultipleBooks() {
|
editMultipleBooks() {
|
||||||
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
const customRoles = getCustomRoles(this.books)
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: this.selectedBooks, roles: customRoles})
|
||||||
},
|
},
|
||||||
bulkEditMultipleBooks() {
|
bulkEditMultipleBooks() {
|
||||||
this.$store.dispatch('dialogUpdateBulkBooks', this.$_.sortBy(this.selectedBooks, ['metadata.numberSort']))
|
this.$store.dispatch('dialogUpdateBulkBooks', this.$_.sortBy(this.selectedBooks, ['metadata.numberSort']))
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ import ItemBrowser from '@/components/ItemBrowser.vue'
|
||||||
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
import ToolbarSticky from '@/components/bars/ToolbarSticky.vue'
|
||||||
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
import LibraryActionsMenu from '@/components/menus/LibraryActionsMenu.vue'
|
||||||
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
import LibraryNavigation from '@/components/LibraryNavigation.vue'
|
||||||
|
import {getCustomRoles, getCustomRolesForSeries, isAllSelectedSameSeries} from '@/functions/author-roles'
|
||||||
import {ReadStatus} from '@/types/enum-books'
|
import {ReadStatus} from '@/types/enum-books'
|
||||||
import {BookDto} from '@/types/komga-books'
|
import {BookDto} from '@/types/komga-books'
|
||||||
import {
|
import {
|
||||||
|
|
@ -495,16 +496,19 @@ export default Vue.extend({
|
||||||
let book = (await this.$komgaBooks.getBooksList({
|
let book = (await this.$komgaBooks.getBooksList({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
||||||
} as BookSearch)).content[0]
|
} as BookSearch)).content[0]
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else {
|
||||||
this.$store.dispatch('dialogUpdateSeries', series)
|
this.$store.dispatch('dialogUpdateSeries', series)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async singleEditBook(book: BookDto) {
|
async singleEditBook(book: BookDto) {
|
||||||
if (book.oneshot) {
|
if (book.oneshot) {
|
||||||
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
|
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else {
|
||||||
this.$store.dispatch('dialogUpdateBooks', book)
|
const customRoles = getCustomRolesForSeries(this.getAllBooksFromLoader(), book.seriesId)
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: book, roles: customRoles})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async markSelectedSeriesRead() {
|
async markSelectedSeriesRead() {
|
||||||
await Promise.all(this.selectedSeries.map(s =>
|
await Promise.all(this.selectedSeries.map(s =>
|
||||||
|
|
@ -532,7 +536,8 @@ export default Vue.extend({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
||||||
} as BookSearch)))
|
} as BookSearch)))
|
||||||
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
|
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
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
||||||
},
|
},
|
||||||
|
|
@ -540,9 +545,15 @@ export default Vue.extend({
|
||||||
if (this.selectedBooks.every(b => b.oneshot)) {
|
if (this.selectedBooks.every(b => b.oneshot)) {
|
||||||
const series = await Promise.all(this.selectedBooks.map(b => this.$komgaSeries.getOneSeries(b.seriesId)))
|
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))
|
const oneshots = this.selectedBooks.map((b, index) => ({series: series[index], book: b} as Oneshot))
|
||||||
this.$store.dispatch('dialogUpdateOneshots', oneshots)
|
const customRole = getCustomRoles(oneshots.map(o => o.book))
|
||||||
} else
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
|
||||||
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
} 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() {
|
deleteSeries() {
|
||||||
this.$store.dispatch('dialogDeleteSeries', this.selectedSeries)
|
this.$store.dispatch('dialogDeleteSeries', this.selectedSeries)
|
||||||
|
|
@ -583,6 +594,15 @@ export default Vue.extend({
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getAllBooksFromLoader(): BookDto[] {
|
||||||
|
return [
|
||||||
|
...(this.loaderInProgressBooks?.items || []),
|
||||||
|
...(this.loaderOnDeckBooks?.items || []),
|
||||||
|
...(this.loaderRecentlyReleasedBooks?.items || []),
|
||||||
|
...(this.loaderLatestBooks?.items || []),
|
||||||
|
...(this.loaderRecentlyReadBooks?.items || []),
|
||||||
|
]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,7 @@ import {
|
||||||
SearchOperatorIsFalse,
|
SearchOperatorIsFalse,
|
||||||
SeriesSearch,
|
SeriesSearch,
|
||||||
} from '@/types/komga-search'
|
} from '@/types/komga-search'
|
||||||
|
import {isAllSelectedSameSeries, getCustomRolesForSeries, getCustomRoles} from '@/functions/author-roles'
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'SearchView',
|
name: 'SearchView',
|
||||||
|
|
@ -317,16 +318,18 @@ export default Vue.extend({
|
||||||
const book = (await this.$komgaBooks.getBooksList({
|
const book = (await this.$komgaBooks.getBooksList({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(series.id)),
|
||||||
} as BookSearch)).content[0]
|
} as BookSearch)).content[0]
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', series)
|
this.$store.dispatch('dialogUpdateSeries', series)
|
||||||
},
|
},
|
||||||
async singleEditBook(book: BookDto) {
|
async singleEditBook(book: BookDto) {
|
||||||
if (book.oneshot) {
|
if (book.oneshot) {
|
||||||
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
|
const series = (await this.$komgaSeries.getOneSeries(book.seriesId))
|
||||||
this.$store.dispatch('dialogUpdateOneshots', {series: series, book: book})
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots: {series: series, book: book}})
|
||||||
} else
|
} else {
|
||||||
this.$store.dispatch('dialogUpdateBooks', book)
|
const customRole = getCustomRolesForSeries(this.loaderBooks?.items || [], book.seriesId)
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: book, roles: customRole})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
singleEditCollection(collection: CollectionDto) {
|
singleEditCollection(collection: CollectionDto) {
|
||||||
this.$store.dispatch('dialogEditCollection', collection)
|
this.$store.dispatch('dialogEditCollection', collection)
|
||||||
|
|
@ -372,7 +375,8 @@ export default Vue.extend({
|
||||||
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
condition: new SearchConditionSeriesId(new SearchOperatorIs(s.id)),
|
||||||
} as BookSearch)))
|
} as BookSearch)))
|
||||||
const oneshots = this.selectedSeries.map((s, index) => ({series: s, book: books[index].content[0]} as Oneshot))
|
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
|
} else
|
||||||
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
this.$store.dispatch('dialogUpdateSeries', this.selectedSeries)
|
||||||
},
|
},
|
||||||
|
|
@ -380,9 +384,15 @@ export default Vue.extend({
|
||||||
if (this.selectedBooks.every(b => b.oneshot)) {
|
if (this.selectedBooks.every(b => b.oneshot)) {
|
||||||
const series = await Promise.all(this.selectedBooks.map(b => this.$komgaSeries.getOneSeries(b.seriesId)))
|
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))
|
const oneshots = this.selectedBooks.map((b, index) => ({series: series[index], book: b} as Oneshot))
|
||||||
this.$store.dispatch('dialogUpdateOneshots', oneshots)
|
const customRole = getCustomRoles(oneshots.map(o => o.book))
|
||||||
} else
|
this.$store.dispatch('dialogUpdateOneshots', {oneshots, roles: customRole})
|
||||||
this.$store.dispatch('dialogUpdateBooks', this.selectedBooks)
|
} else {
|
||||||
|
let customRole = [] as string[]
|
||||||
|
if (isAllSelectedSameSeries(this.selectedBooks)) {
|
||||||
|
customRole = getCustomRolesForSeries(this.loaderBooks?.items || [], this.selectedBooks[0].seriesId)
|
||||||
|
}
|
||||||
|
this.$store.dispatch('dialogUpdateBooks', {books: this.selectedBooks, roles: customRole})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
bulkEditMultipleBooks() {
|
bulkEditMultipleBooks() {
|
||||||
this.$store.dispatch('dialogUpdateBulkBooks', this.selectedBooks)
|
this.$store.dispatch('dialogUpdateBulkBooks', this.selectedBooks)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue