Skip to content

Commit

Permalink
feat: add more series metadata fields
Browse files Browse the repository at this point in the history
title, sort title, lock for: status, title and sort title
  • Loading branch information
gotson committed Jan 31, 2020
1 parent f1952ee commit 8f08ce8
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 123 deletions.
4 changes: 2 additions & 2 deletions komga-webui/src/components/CardSeries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<v-card-subtitle class="pa-2 pb-1 text--primary"
v-line-clamp="2"
style="word-break: normal !important; height: 4em"
:title="series.name"
:title="series.metadata.title"
>
{{ series.name }}
{{ series.metadata.title }}
</v-card-subtitle>

<v-card-text class="px-2"
Expand Down
87 changes: 74 additions & 13 deletions komga-webui/src/components/EditSeriesDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<v-btn icon @click="dialogCancel">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-toolbar-title>Edit {{ series.name }}</v-toolbar-title>
<v-toolbar-title>Edit {{ $_.get(series, 'metadata.title') }}</v-toolbar-title>
<v-spacer/>
<v-toolbar-items>
<v-btn text color="primary" @click="dialogConfirm">Save changes</v-btn>
Expand All @@ -18,7 +18,7 @@

<v-card-title class="hidden-xs-only">
<v-icon class="mr-4">mdi-pencil</v-icon>
Edit {{ series.name }}
Edit {{ $_.get(series, 'metadata.title') }}
</v-card-title>

<v-tabs :vertical="$vuetify.breakpoint.smAndUp">
Expand All @@ -32,13 +32,59 @@
<v-card flat>
<form novalidate>
<v-container fluid>

<!-- Title -->
<v-row>
<v-col cols="12">
<v-text-field v-model="form.title"
label="Title"
@change="form.titleLock = true"
>
<template v-slot:prepend>
<v-icon :color="form.titleLock ? 'secondary' : ''"
@click="form.titleLock = !form.titleLock"
>
{{ form.titleLock ? 'mdi-lock' : 'mdi-lock-open' }}
</v-icon>
</template>
</v-text-field>
</v-col>
</v-row>

<!-- Sort Title -->
<v-row>
<v-col cols="12">
<v-text-field v-model="form.titleSort"
label="Sort Title"
@change="form.titleSortLock = true"
>
<template v-slot:prepend>
<v-icon :color="form.titleSortLock ? 'secondary' : ''"
@click="form.titleSortLock = !form.titleSortLock"
>
{{ form.titleSortLock ? 'mdi-lock' : 'mdi-lock-open' }}
</v-icon>
</template>
</v-text-field>
</v-col>
</v-row>

<!-- Status -->
<v-row>
<v-col cols="auto">
<v-select
:items="seriesStatus"
v-model="form.status"
label="Status"
/>
<v-select :items="seriesStatus"
v-model="form.status"
label="Status"
@change="form.statusLock = true"
>
<template v-slot:prepend>
<v-icon :color="form.statusLock ? 'secondary' : ''"
@click="form.statusLock = !form.statusLock"
>
{{ form.statusLock ? 'mdi-lock' : 'mdi-lock-open' }}
</v-icon>
</template>
</v-select>
</v-col>
</v-row>
</v-container>
Expand Down Expand Up @@ -86,7 +132,12 @@ export default Vue.extend({
snackText: '',
seriesStatus: Object.keys(SeriesStatus).map(x => capitalize(x)),
form: {
status: ''
status: '',
statusLock: false,
title: '',
titleLock: false,
titleSort: '',
titleSortLock: false
}
}
},
Expand Down Expand Up @@ -116,15 +167,19 @@ export default Vue.extend({
methods: {
dialogReset (series: SeriesDto) {
this.form.status = capitalize(series.metadata.status)
this.form.statusLock = series.metadata.statusLock
this.form.title = series.metadata.title
this.form.titleLock = series.metadata.titleLock
this.form.titleSort = series.metadata.titleSort
this.form.titleSortLock = series.metadata.titleSortLock
},
dialogCancel () {
this.$emit('input', false)
this.dialogReset(this.series)
},
dialogConfirm () {
this.editSeries()
async dialogConfirm () {
await this.editSeries()
this.$emit('input', false)
this.dialogReset(this.series)
},
showSnack (message: string) {
this.snackText = message
Expand All @@ -133,10 +188,16 @@ export default Vue.extend({
async editSeries () {
try {
const metadata = {
status: this.form.status.toUpperCase()
status: this.form.status.toUpperCase(),
statusLock: this.form.statusLock,
title: this.form.title,
titleLock: this.form.titleLock,
titleSort: this.form.titleSort,
titleSortLock: this.form.titleSortLock
} as SeriesMetadataUpdateDto
await this.$komgaSeries.updateMetadata(this.series.id, metadata)
const updatedSeries = await this.$komgaSeries.updateMetadata(this.series.id, metadata)
this.$emit('update:series', updatedSeries)
} catch (e) {
this.showSnack(e.message)
}
Expand Down
2 changes: 1 addition & 1 deletion komga-webui/src/components/SearchBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
class="ma-1 mr-3"
/>
<v-list-item-content>
<v-list-item-title v-text="item.name"/>
<v-list-item-title v-text="item.metadata.title"/>
</v-list-item-content>
</v-list-item>
</template>
Expand Down
4 changes: 2 additions & 2 deletions komga-webui/src/services/komga-series.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ export default class KomgaSeriesService {
}
}

async updateMetadata (seriesId: number, metadata: SeriesMetadataUpdateDto) {
async updateMetadata (seriesId: number, metadata: SeriesMetadataUpdateDto): Promise<SeriesDto> {
try {
await this.http.patch(`${API_SERIES}/${seriesId}/metadata`, metadata)
return (await this.http.patch(`${API_SERIES}/${seriesId}/metadata`, metadata)).data
} catch (e) {
let msg = `An error occurred while trying to update series metadata`
if (e.response.data.message) {
Expand Down
14 changes: 12 additions & 2 deletions komga-webui/src/types/komga-series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ interface SeriesDto {

interface SeriesMetadata {
status: string,
statusLock: boolean,
created: string,
lastModified: string
lastModified: string,
title: string,
titleLock: boolean,
titleSort: string,
titleSortLock: boolean
}

interface SeriesMetadataUpdateDto {
status?: string
status?: string,
statusLock?: boolean,
title?: string,
titleLock?: boolean,
titleSort?: string,
titleSortLock?: boolean
}
11 changes: 6 additions & 5 deletions komga-webui/src/views/BrowseLibraries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,13 @@ export default mixins(VisibleElements).extend({
pagesState: [] as LoadState[],
pageSize: 20,
totalElements: null as number | null,
sortOptions: [{ name: 'Name', key: 'name' }, { name: 'Date added', key: 'createdDate' }, {
name: 'Date updated',
key: 'lastModifiedDate'
}] as SortOption[],
sortOptions: [
{ name: 'Name', key: 'metadata.titleSort' },
{ name: 'Date added', key: 'createdDate' },
{ name: 'Date updated', key: 'lastModifiedDate' }
] as SortOption[],
sortActive: {} as SortActive,
sortDefault: { key: 'name', order: 'asc' } as SortActive,
sortDefault: { key: 'metadata.titleSort', order: 'asc' } as SortActive,
filterStatus: [] as string[],
SeriesStatus,
cardWidth: 150,
Expand Down
11 changes: 3 additions & 8 deletions komga-webui/src/views/BrowseSeries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
</v-menu>

<v-toolbar-title>
<span v-if="series.name">{{ series.name }}</span>
<span v-if="$_.get(series, 'metadata.title')">{{ series.metadata.title }}</span>
<badge class="ml-4" v-if="totalElements" v-model="totalElements"/>
</v-toolbar-title>

Expand Down Expand Up @@ -54,7 +54,7 @@
<v-col cols="8">
<v-row>
<v-col>
<div class="headline" v-if="series.name">{{ series.name }}</div>
<div class="headline" v-if="$_.get(series, 'metadata.title')">{{ series.metadata.title }}</div>
</v-col>
</v-row>

Expand Down Expand Up @@ -89,7 +89,7 @@
</v-container>

<edit-series-dialog v-model="dialogEdit"
:series="series"/>
:series.sync="series"/>
</div>
</template>

Expand Down Expand Up @@ -159,11 +159,6 @@ export default mixins(VisibleElements).extend({
if (this.$route.params.index !== index) {
this.updateRoute(index)
}
},
dialogEdit (val) {
if (!val) {
this.loadSeries()
}
}
},
async created () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class Series(

@OneToOne(optional = false, orphanRemoval = true, cascade = [CascadeType.ALL], fetch = FetchType.LAZY)
@JoinColumn(name = "metadata_id", nullable = false)
var metadata: SeriesMetadata = SeriesMetadata()
var metadata: SeriesMetadata = SeriesMetadata(title = name, titleSort = name)

init {
this.books = books.toList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,29 @@ import javax.persistence.Table
class SeriesMetadata(
@Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false)
var status: Status = Status.ONGOING
var status: Status = Status.ONGOING,

@Column(name = "title", nullable = false)
var title: String,

@Column(name = "title_sort", nullable = false)
var titleSort: String

) : AuditableEntity() {
@Id
@GeneratedValue
@Column(name = "id", nullable = false, unique = true)
val id: Long = 0

@Column(name = "status_lock", nullable = false)
var statusLock: Boolean = false

@Column(name = "title_lock", nullable = false)
var titleLock: Boolean = false

@Column(name = "title_sort_lock", nullable = false)
var titleSortLock: Boolean = false

enum class Status {
ENDED, ONGOING, ABANDONED, HIATUS
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,16 @@ class OpdsController(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam("search") searchTerm: String?
): OpdsFeed {
val sort = Sort.by(Sort.Order.asc("name").ignoreCase())
val sort = Sort.by(Sort.Order.asc("metadata.titleSort").ignoreCase())
val series =
mutableListOf<Specification<Series>>().let { specs ->
if (!principal.user.sharedAllLibraries) {
specs.add(Series::library.`in`(principal.user.sharedLibraries))
}
mutableListOf<Specification<Series>>().let { specs ->
if (!principal.user.sharedAllLibraries) {
specs.add(Series::library.`in`(principal.user.sharedLibraries))
}

if (!searchTerm.isNullOrEmpty()) {
specs.add(Series::name.likeLower("%$searchTerm%"))
}
if (!searchTerm.isNullOrEmpty()) {
specs.add(Series::name.likeLower("%$searchTerm%"))
}

if (specs.isNotEmpty()) {
seriesRepository.findAll(specs.reduce { acc, spec -> acc.and(spec)!! }, sort)
Expand Down Expand Up @@ -230,14 +230,14 @@ class OpdsController(
OpdsLinkFeedNavigation(OpdsLinkRel.SELF, "${ROUTE_BASE}libraries/$id"),
linkStart
),
entries = seriesRepository.findByLibraryId(library.id, Sort.by(Sort.Order.asc("name").ignoreCase())).map { it.toOpdsEntry() }
entries = seriesRepository.findByLibraryId(library.id, Sort.by(Sort.Order.asc("metadata.titleSort").ignoreCase())).map { it.toOpdsEntry() }
)
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)


private fun Series.toOpdsEntry() =
OpdsEntryNavigation(
title = name,
title = metadata.title,
updated = lastModifiedDate?.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
id = id.toString(),
content = "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class SeriesController(
page.pageNumber,
page.pageSize,
if (page.sort.isSorted) page.sort
else Sort.by(Sort.Order.asc("name").ignoreCase())
else Sort.by(Sort.Order.asc("metadata.titleSort").ignoreCase())
)

return mutableListOf<Specification<Series>>().let { specs ->
Expand Down Expand Up @@ -226,6 +226,15 @@ class SeriesController(
): SeriesDto =
seriesRepository.findByIdOrNull(seriesId)?.let { series ->
newMetadata.status?.let { series.metadata.status = newMetadata.status }
newMetadata.statusLock?.let { series.metadata.statusLock = newMetadata.statusLock }
if (!newMetadata.title.isNullOrBlank()) {
series.metadata.title = newMetadata.title
}
newMetadata.titleLock?.let { series.metadata.titleLock = newMetadata.titleLock }
if (!newMetadata.titleSort.isNullOrBlank()) {
series.metadata.titleSort = newMetadata.titleSort
}
newMetadata.titleSortLock?.let { series.metadata.titleSortLock = newMetadata.titleSortLock }
seriesRepository.save(series).toDto(includeUrl = true)
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,15 @@ data class SeriesDto(

data class SeriesMetadataDto(
val status: String,
val statusLock: Boolean,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val created: LocalDateTime?,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val lastModified: LocalDateTime?
val lastModified: LocalDateTime?,
val title: String,
val titleLock: Boolean,
val titleSort: String,
val titleSortLock: Boolean
)

fun Series.toDto(includeUrl: Boolean) = SeriesDto(
Expand All @@ -38,7 +43,12 @@ fun Series.toDto(includeUrl: Boolean) = SeriesDto(
booksCount = books.size,
metadata = SeriesMetadataDto(
status = metadata.status.name,
statusLock = metadata.statusLock,
created = metadata.createdDate?.toUTC(),
lastModified = metadata.lastModifiedDate?.toUTC()
lastModified = metadata.lastModifiedDate?.toUTC(),
title = metadata.title,
titleLock = metadata.titleLock,
titleSort = metadata.titleSort,
titleSortLock = metadata.titleSortLock
)
)

0 comments on commit 8f08ce8

Please sign in to comment.