feat(webui): library option to automatically empty trash after scan

This commit is contained in:
Gauthier Roebroeck 2021-07-09 15:21:50 +08:00
parent 21781a3a23
commit fc06b4a987
3 changed files with 244 additions and 214 deletions

View file

@ -2,7 +2,8 @@
<v-dialog v-model="modal"
:fullscreen="this.$vuetify.breakpoint.xsOnly"
:hide-overlay="this.$vuetify.breakpoint.xsOnly"
max-width="600"
max-width="700"
scrollable
>
<form novalidate>
<v-card>
@ -13,217 +14,244 @@
<v-toolbar-title>{{ dialogTitle }}</v-toolbar-title>
<v-spacer/>
<v-toolbar-items>
<v-btn text color="primary" @click="dialogConfirm">{{ confirmText }}</v-btn>
<v-btn text color="primary" @click="nextTab" v-if="showNext">
{{ $t('dialog.edit_library.button_next') }}
</v-btn>
<v-btn text color="primary" @click="dialogConfirm" v-else>{{ confirmText }}</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-card-title class="hidden-xs-only">{{ dialogTitle }}</v-card-title>
<v-tabs :vertical="$vuetify.breakpoint.smAndUp" v-model="tab">
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-bookshelf</v-icon>
{{ $t('dialog.edit_library.tab_general') }}
</v-tab>
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-tune</v-icon>
{{ $t('dialog.edit_library.tab_options') }}
</v-tab>
<v-card-text class="pa-0">
<v-tabs :vertical="$vuetify.breakpoint.smAndUp" v-model="tab">
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-bookshelf</v-icon>
{{ $t('dialog.edit_library.tab_general') }}
</v-tab>
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-tune</v-icon>
{{ $t('dialog.edit_library.tab_options') }}
</v-tab>
<v-tab class="justify-start">
<v-icon left class="hidden-xs-only">mdi-book-information-variant</v-icon>
{{ $t('dialog.edit_library.tab_metadata') }}
</v-tab>
<!-- Tab: General -->
<v-tab-item>
<v-card flat>
<v-container fluid>
<!-- Tab: General -->
<v-tab-item>
<v-card flat :min-height="$vuetify.breakpoint.xs ? $vuetify.breakpoint.height * .8 : undefined">
<v-container fluid>
<v-row>
<v-col>
<v-text-field v-model="form.name"
autofocus
:label="$t('dialog.edit_library.field_name')"
:error-messages="getErrors('name')"
@input="$v.form.name.$touch()"
@blur="$v.form.name.$touch()"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-text-field v-model="form.name"
autofocus
:label="$t('dialog.edit_library.field_name')"
:error-messages="getErrors('name')"
@input="$v.form.name.$touch()"
@blur="$v.form.name.$touch()"
/>
</v-col>
</v-row>
<v-row justify="center">
<v-col cols="8" align-self="center">
<file-browser-dialog
v-model="modalFileBrowser"
:path.sync="form.path"
:confirm-text="$t('dialog.edit_library.file_browser_dialog_button_confirm')"
:dialog-title="$t('dialog.edit_library.file_browser_dialog_title')"
/>
<v-row justify="center">
<v-col cols="8" align-self="center">
<file-browser-dialog
v-model="modalFileBrowser"
:path.sync="form.path"
:confirm-text="$t('dialog.edit_library.file_browser_dialog_button_confirm')"
:dialog-title="$t('dialog.edit_library.file_browser_dialog_title')"
/>
<v-text-field v-model="form.path"
:label="$t('dialog.edit_library.field_root_folder')"
:error-messages="getErrors('path')"
@input="$v.form.path.$touch()"
@blur="$v.form.path.$touch()"
/>
</v-col>
<v-col cols="4" align-self="center">
<v-btn @click="modalFileBrowser = true">{{ $t('dialog.edit_library.button_browse') }}</v-btn>
</v-col>
</v-row>
</v-container>
</v-card>
</v-tab-item>
<v-text-field v-model="form.path"
:label="$t('dialog.edit_library.field_root_folder')"
:error-messages="getErrors('path')"
@input="$v.form.path.$touch()"
@blur="$v.form.path.$touch()"
/>
</v-col>
<v-col cols="4" align-self="center">
<v-btn @click="modalFileBrowser = true">{{ $t('dialog.edit_library.button_browse') }}</v-btn>
</v-col>
</v-row>
</v-container>
</v-card>
</v-tab-item>
<!-- Tab: Options -->
<v-tab-item>
<v-card flat>
<v-container fluid>
<v-row>
<v-col>
<v-checkbox
v-model="importComicInfo"
:indeterminate="importComicInfo === 1"
hide-details
>
<template v-slot:label>
<span class="text-subtitle-2 text--primary">{{
<!-- Tab: Options -->
<v-tab-item>
<v-card flat :min-height="$vuetify.breakpoint.xs ? $vuetify.breakpoint.height * .8 : undefined">
<v-container fluid>
<v-row>
<v-col cols="auto">
<span class="text-subtitle-1 text--primary">{{ $t('dialog.edit_library.label_scanner') }}</span>
<v-checkbox
v-model="form.emptyTrashAfterScan"
:label="$t('dialog.edit_library.field_scanner_empty_trash_after_scan')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.scanForceModifiedTime"
:label="$t('dialog.edit_library.field_scanner_force_directory_modified_time')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.scanDeep"
:label="$t('dialog.edit_library.field_scanner_deep_scan')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-checkbox
v-model="fileManagement"
:indeterminate="fileManagement === 1"
hide-details
:label="$t('dialog.edit_library.label_file_management')"
>
<template v-slot:label>
<span class="text-subtitle-1 text--primary">{{
$t('dialog.edit_library.label_file_management')
}}</span>
</template>
</v-checkbox>
<v-checkbox
v-model="form.repairExtensions"
:label="$t('dialog.edit_library.field_repair_extensions')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.convertToCbz"
:label="$t('dialog.edit_library.field_convert_to_cbz')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
</v-container>
</v-card>
</v-tab-item>
<!-- Tab: Metadata -->
<v-tab-item>
<v-card flat :min-height="$vuetify.breakpoint.xs ? $vuetify.breakpoint.height * .8 : undefined">
<v-container fluid>
<v-row>
<v-col>
<v-checkbox
v-model="importComicInfo"
:indeterminate="importComicInfo === 1"
hide-details
>
<template v-slot:label>
<span class="text-subtitle-1 text--primary">{{
$t('dialog.edit_library.label_import_comicinfo')
}}</span>
</template>
</v-checkbox>
<v-checkbox
v-model="form.importComicInfoBook"
:label="$t('dialog.edit_library.field_import_comicinfo_book')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoSeries"
:label="$t('dialog.edit_library.field_import_comicinfo_series')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoCollection"
:label="$t('dialog.edit_library.field_import_comicinfo_collections')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoReadList"
:label="$t('dialog.edit_library.field_import_comicinfo_readlists')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-checkbox
v-model="importEpub"
:indeterminate="importEpub === 1"
hide-details
>
<template v-slot:label>
<span class="text-subtitle-2 text--primary">{{
</template>
</v-checkbox>
<v-checkbox
v-model="form.importComicInfoBook"
:label="$t('dialog.edit_library.field_import_comicinfo_book')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoSeries"
:label="$t('dialog.edit_library.field_import_comicinfo_series')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoCollection"
:label="$t('dialog.edit_library.field_import_comicinfo_collections')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importComicInfoReadList"
:label="$t('dialog.edit_library.field_import_comicinfo_readlists')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-checkbox
v-model="importEpub"
:indeterminate="importEpub === 1"
hide-details
>
<template v-slot:label>
<span class="text-subtitle-1 text--primary">{{
$t('dialog.edit_library.label_import_epub')
}}</span>
</template>
</v-checkbox>
<v-checkbox
v-model="form.importEpubBook"
:label="$t('dialog.edit_library.field_import_epub_book')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importEpubSeries"
:label="$t('dialog.edit_library.field_import_epub_series')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<span class="text-subtitle-2">{{ $t('dialog.edit_library.label_import_local') }}</span>
<v-checkbox
v-model="form.importLocalArtwork"
:label="$t('dialog.edit_library.field_import_local_artwork')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<span class="text-subtitle-2">{{ $t('dialog.edit_library.label_import_barcode_isbn') }}</span>
<v-checkbox
v-model="form.importBarcodeIsbn"
:label="$t('dialog.edit_library.field_import_barcode_isbn')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col cols="auto">
<v-checkbox
v-model="scanner"
:indeterminate="scanner === 1"
hide-details
>
<template v-slot:label>
<span class="text-subtitle-2 text--primary">{{ $t('dialog.edit_library.label_scanner') }}</span>
</template>
</v-checkbox>
<v-checkbox
v-model="form.scanForceModifiedTime"
:label="$t('dialog.edit_library.field_scanner_force_directory_modified_time')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.scanDeep"
:label="$t('dialog.edit_library.field_scanner_deep_scan')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-checkbox
v-model="fileManagement"
:indeterminate="fileManagement === 1"
hide-details
>
<template v-slot:label>
<span class="text-subtitle-2">{{ $t('dialog.edit_library.label_file_management') }}</span>
</template>
</v-checkbox>
</template>
</v-checkbox>
<v-checkbox
v-model="form.importEpubBook"
:label="$t('dialog.edit_library.field_import_epub_book')"
hide-details
class="mx-4"
/>
<v-checkbox
v-model="form.importEpubSeries"
:label="$t('dialog.edit_library.field_import_epub_series')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<span class="text-subtitle-1 text--primary">{{
$t('dialog.edit_library.label_import_local')
}}</span>
<v-checkbox
v-model="form.importLocalArtwork"
:label="$t('dialog.edit_library.field_import_local_artwork')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<span class="text-subtitle-1 text--primary">{{
$t('dialog.edit_library.label_import_barcode_isbn')
}}</span>
<v-checkbox
v-model="form.importBarcodeIsbn"
:label="$t('dialog.edit_library.field_import_barcode_isbn')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
<v-checkbox
v-model="form.repairExtensions"
:label="$t('dialog.edit_library.field_repair_extensions')"
hide-details
class="mx-4"
/>
</v-container>
</v-card>
</v-tab-item>
<v-checkbox
v-model="form.convertToCbz"
:label="$t('dialog.edit_library.field_convert_to_cbz')"
hide-details
class="mx-4"
/>
</v-col>
</v-row>
</v-container>
</v-card>
</v-tab-item>
</v-tabs>
</v-tabs>
</v-card-text>
<v-card-actions class="hidden-xs-only">
<v-spacer/>
<v-btn text @click="dialogClose">{{ $t('dialog.edit_library.button_cancel') }}</v-btn>
<v-btn color="primary" @click="dialogConfirm">{{ confirmText }}</v-btn>
<v-btn color="primary" @click="nextTab" v-if="showNext">
{{ $t('dialog.edit_library.button_next') }}
</v-btn>
<v-btn color="primary" @click="dialogConfirm" v-else>{{ confirmText }}</v-btn>
</v-card-actions>
</v-card>
</form>
@ -259,6 +287,7 @@ export default Vue.extend({
scanDeep: false,
repairExtensions: false,
convertToCbz: false,
emptyTrashAfterScan: false,
},
validationFieldNames: new Map([]),
}
@ -270,6 +299,9 @@ export default Vue.extend({
confirmText(): string {
return this.library ? this.$t('dialog.edit_library.button_confirm_edit').toString() : this.$t('dialog.edit_library.button_confirm_add').toString()
},
showNext(): boolean {
return !this.library && this.tab !== 2
},
importComicInfo: {
get: function (): number {
@ -301,20 +333,6 @@ export default Vue.extend({
},
},
scanner: {
get: function (): number {
const val = [this.form.scanDeep, this.form.scanForceModifiedTime]
const count = val.filter(Boolean).length
if (count === val.length) return 2
if (count === 0) return 0
return 1
},
set: function (value: boolean): void {
this.form.scanDeep = value
this.form.scanForceModifiedTime = value
},
},
fileManagement: {
get: function (): number {
const val = [this.form.repairExtensions, this.form.convertToCbz]
@ -352,6 +370,10 @@ export default Vue.extend({
},
},
methods: {
nextTab() {
this.$v.$touch()
if (!this.$v.$invalid) this.tab += 1
},
getErrors(fieldName: string) {
const errors = []
@ -385,6 +407,7 @@ export default Vue.extend({
this.form.scanDeep = library ? library.scanDeep : false
this.form.repairExtensions = library ? library.repairExtensions : false
this.form.convertToCbz = library ? library.convertToCbz : false
this.form.emptyTrashAfterScan = library ? library.emptyTrashAfterScan : false
this.$v.$reset()
},
validateLibrary() {
@ -406,6 +429,7 @@ export default Vue.extend({
scanDeep: this.form.scanDeep,
repairExtensions: this.form.repairExtensions,
convertToCbz: this.form.convertToCbz,
emptyTrashAfterScan: this.form.emptyTrashAfterScan,
}
}
return null

View file

@ -322,6 +322,7 @@
"button_cancel": "Cancel",
"button_confirm_add": "Add",
"button_confirm_edit": "Edit",
"button_next": "Next",
"dialog_title_add": "Add Library",
"dialot_title_edit": "Edit Library",
"field_convert_to_cbz": "Automatically convert to CBZ",
@ -337,6 +338,7 @@
"field_repair_extensions": "Automatically repair incorrect file extensions",
"field_root_folder": "Root folder",
"field_scanner_deep_scan": "Deep scan",
"field_scanner_empty_trash_after_scan": "Empty trash automatically after every scan",
"field_scanner_force_directory_modified_time": "Force directory modified time",
"file_browser_dialog_button_confirm": "Choose",
"file_browser_dialog_title": "Library's root folder",
@ -347,6 +349,7 @@
"label_import_local": "Import local media assets",
"label_scanner": "Scanner",
"tab_general": "General",
"tab_metadata": "Metadata",
"tab_options": "Options"
},
"edit_readlist": {
@ -389,6 +392,11 @@
"field_all_libraries": "All libraries",
"label_shared_with": "Shared with {name}"
},
"empty_trash": {
"body": "By default the media server doesn't remove information for media right away. This helps if a drive is temporarily disconnected. When you empty the trash for a library, all information about missing media is deleted.",
"button_confirm": "Empty",
"title": "Empty trash for library"
},
"file_browser": {
"button_cancel": "Cancel",
"button_confirm_default": "Choose",
@ -455,11 +463,6 @@
"page_of_pages": "{page} / {pages}",
"title": "Inspect Book",
"title_comparison": "Book Comparison"
},
"empty_trash": {
"title": "Empty trash for library",
"body": "By default the media server doesn't remove information for media right away. This helps if a drive is temporarily disconnected. When you empty the trash for a library, all information about missing media is deleted.",
"button_confirm": "Empty"
}
},
"enums": {

View file

@ -12,7 +12,8 @@ interface LibraryCreationDto {
scanForceModifiedTime: boolean,
scanDeep: boolean,
repairExtensions: boolean,
convertToCbz: boolean
convertToCbz: boolean,
emptyTrashAfterScan: boolean,
}
interface LibraryUpdateDto {
@ -29,7 +30,8 @@ interface LibraryUpdateDto {
scanForceModifiedTime: boolean,
scanDeep: boolean,
repairExtensions: boolean,
convertToCbz: boolean
convertToCbz: boolean,
emptyTrashAfterScan: boolean,
}
interface LibraryDto {
@ -47,5 +49,6 @@ interface LibraryDto {
scanForceModifiedTime: boolean,
scanDeep: boolean,
repairExtensions: boolean,
convertToCbz: boolean
convertToCbz: boolean,
emptyTrashAfterScan: boolean,
}