.kavitaignore no more (#2442)

This commit is contained in:
Joe Milazzo 2023-11-19 12:15:32 -06:00 committed by GitHub
parent cd27efecdd
commit 7221501c4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
91 changed files with 5968 additions and 1026 deletions

View file

@ -21,7 +21,7 @@ import {NavService} from "../../../_services/nav.service";
import {DashboardStreamListItemComponent} from "../dashboard-stream-list-item/dashboard-stream-list-item.component";
import {TranslocoDirective} from "@ngneat/transloco";
import {SidenavStreamListItemComponent} from "../sidenav-stream-list-item/sidenav-stream-list-item.component";
import {ExternalSourceService} from "../../../external-source.service";
import {ExternalSourceService} from "../../../_services/external-source.service";
import {ExternalSource} from "../../../_models/sidenav/external-source";
import {SideNavStreamType} from "../../../_models/sidenav/sidenav-stream-type.enum";
import {FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";

View file

@ -4,7 +4,7 @@ import {FormControl, FormGroup, ReactiveFormsModule, Validators} from "@angular/
import {ExternalSource} from "../../../_models/sidenav/external-source";
import {NgbCollapse} from "@ng-bootstrap/ng-bootstrap";
import {translate, TranslocoDirective} from "@ngneat/transloco";
import {ExternalSourceService} from "../../../external-source.service";
import {ExternalSourceService} from "../../../_services/external-source.service";
import {distinctUntilChanged, filter, tap} from "rxjs/operators";
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {switchMap} from "rxjs";

View file

@ -7,7 +7,7 @@ import {AccountService} from "../../../_services/account.service";
import {ToastrService} from "ngx-toastr";
import {EditExternalSourceItemComponent} from "../edit-external-source-item/edit-external-source-item.component";
import {ExternalSource} from "../../../_models/sidenav/external-source";
import {ExternalSourceService} from "../../../external-source.service";
import {ExternalSourceService} from "../../../_services/external-source.service";
import {FilterPipe} from "../../../_pipes/filter.pipe";
import {SmartFilter} from "../../../_models/metadata/v2/smart-filter";

View file

@ -13,7 +13,7 @@ import { ImportCblModalComponent } from 'src/app/reading-list/_modals/import-cbl
import { ImageService } from 'src/app/_services/image.service';
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
import { Breakpoint, UtilityService } from '../../../shared/_services/utility.service';
import { Library, LibraryType } from '../../../_models/library';
import { Library, LibraryType } from '../../../_models/library/library';
import { AccountService } from '../../../_services/account.service';
import { Action, ActionFactoryService, ActionItem } from '../../../_services/action-factory.service';
import { ActionService } from '../../../_services/action.service';
@ -186,6 +186,8 @@ export class SideNavComponent implements OnInit {
case LibraryType.Comic:
case LibraryType.Manga:
return 'fa-book-open';
case LibraryType.Images:
return 'fa-images';
}
}

View file

@ -88,6 +88,48 @@
<li [ngbNavItem]="TabID.Advanced" [disabled]="isAddLibrary && setupStep < 3">
<a ngbNavLink>{{t(TabID.Advanced)}}</a>
<ng-template ngbNavContent>
<div class="row">
<div class="col-md-12 col-sm-12 pe-2 mb-2">
<div class="mb-3 mt-1">
<h6>{{t('file-type-group-label')}}</h6>
<p class="accent">
{{t('file-type-group-tooltip')}}
</p>
<div class="hstack gap-2">
<div class="form-check form-switch" *ngFor="let group of fileTypeGroups; let i = index">
<input class="form-check-input" [formControlName]="group" type="checkbox" [id]="group">
<label class="form-check-label" [for]="group">{{ group | fileTypeGroup }}</label>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12 pe-2 mb-2">
<div ngbAccordion>
<div ngbAccordionItem>
<h2 ngbAccordionHeader>
<button ngbAccordionButton>{{t('exclude-patterns-label')}}</button>
</h2>
<div ngbAccordionCollapse>
<div ngbAccordionBody>
<ng-template>
<span class="mb-2">{{t('exclude-patterns-tooltip')}}</span>
<a class="ms-1" href="https://wiki.kavitareader.com/en/guides/managing-your-files/scanner/excluding-files-folders" rel="noopener noreferrer" target="_blank">{{t('help')}}<i class="fa fa-external-link-alt ms-1" aria-hidden="true"></i></a>
<app-edit-list [items]="excludePatterns" [label]="t('exclude-patterns-label')" (updateItems)="updateGlobs($event)"></app-edit-list>
</ng-template>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12 pe-2 mb-2">
<div class="mb-3 mt-1">

View file

@ -1,6 +1,18 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, Input, OnInit} from '@angular/core';
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
DestroyRef,
inject,
Input,
OnInit
} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import {
NgbAccordionBody,
NgbAccordionButton, NgbAccordionCollapse,
NgbAccordionDirective, NgbAccordionHeader, NgbAccordionItem,
NgbActiveModal,
NgbModal,
NgbModalModule,
@ -20,7 +32,7 @@ import {
} from 'src/app/admin/_modals/directory-picker/directory-picker.component';
import {ConfirmService} from 'src/app/shared/confirm.service';
import {Breakpoint, UtilityService} from 'src/app/shared/_services/utility.service';
import {Library, LibraryType} from 'src/app/_models/library';
import {Library, LibraryType} from 'src/app/_models/library/library';
import {ImageService} from 'src/app/_services/image.service';
import {LibraryService} from 'src/app/_services/library.service';
import {UploadService} from 'src/app/_services/upload.service';
@ -30,6 +42,9 @@ import {SentenceCasePipe} from "../../../_pipes/sentence-case.pipe";
import {CoverImageChooserComponent} from "../../../cards/cover-image-chooser/cover-image-chooser.component";
import {translate, TranslocoModule} from "@ngneat/transloco";
import {DefaultDatePipe} from "../../../_pipes/default-date.pipe";
import {allFileTypeGroup, FileTypeGroup} from "../../../_models/library/file-type-group.enum";
import {FileTypeGroupPipe} from "../../../_pipes/file-type-group.pipe";
import {EditListComponent} from "../../../shared/edit-list/edit-list.component";
enum TabID {
General = 'general-tab',
@ -48,7 +63,9 @@ enum StepID {
@Component({
selector: 'app-library-settings-modal',
standalone: true,
imports: [CommonModule, NgbModalModule, NgbNavLink, NgbNavItem, NgbNavContent, ReactiveFormsModule, NgbTooltip, SentenceCasePipe, NgbNav, NgbNavOutlet, CoverImageChooserComponent, TranslocoModule, DefaultDatePipe],
imports: [CommonModule, NgbModalModule, NgbNavLink, NgbNavItem, NgbNavContent, ReactiveFormsModule, NgbTooltip,
SentenceCasePipe, NgbNav, NgbNavOutlet, CoverImageChooserComponent, TranslocoModule, DefaultDatePipe,
FileTypeGroupPipe, NgbAccordionDirective, NgbAccordionItem, NgbAccordionHeader, NgbAccordionButton, NgbAccordionCollapse, NgbAccordionBody, EditListComponent],
templateUrl: './library-settings-modal.component.html',
styleUrls: ['./library-settings-modal.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
@ -81,23 +98,24 @@ export class LibrarySettingsModalComponent implements OnInit {
isAddLibrary = false;
setupStep = StepID.General;
fileTypeGroups = allFileTypeGroup;
excludePatterns: Array<string> = [''];
protected readonly Breakpoint = Breakpoint;
protected readonly TabID = TabID;
constructor(public utilityService: UtilityService, private uploadService: UploadService, private modalService: NgbModal,
private settingService: SettingsService, public modal: NgbActiveModal, private confirmService: ConfirmService,
private libraryService: LibraryService, private toastr: ToastrService, private readonly cdRef: ChangeDetectorRef,
private imageService: ImageService) { }
ngOnInit(): void {
this.settingService.getLibraryTypes().subscribe((types) => {
this.libraryTypes = types;
this.cdRef.markForCheck();
});
if (this.library === undefined) {
this.isAddLibrary = true;
this.cdRef.markForCheck();
@ -113,7 +131,6 @@ export class LibrarySettingsModalComponent implements OnInit {
this.libraryForm.get('allowScrobbling')?.disable();
}
this.libraryForm.get('name')?.valueChanges.pipe(
debounceTime(100),
distinctUntilChanged(),
@ -132,6 +149,38 @@ export class LibrarySettingsModalComponent implements OnInit {
this.setValues();
// This needs to only apply after first render
this.libraryForm.get('type')?.valueChanges.pipe(
tap((type: LibraryType) => {
switch (type) {
case LibraryType.Manga:
this.libraryForm.get(FileTypeGroup.Archive + '')?.setValue(true);
this.libraryForm.get(FileTypeGroup.Images + '')?.setValue(true);
this.libraryForm.get(FileTypeGroup.Pdf + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Epub + '')?.setValue(false);
break;
case LibraryType.Comic:
this.libraryForm.get(FileTypeGroup.Archive + '')?.setValue(true);
this.libraryForm.get(FileTypeGroup.Images + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Pdf + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Epub + '')?.setValue(false);
break;
case LibraryType.Book:
this.libraryForm.get(FileTypeGroup.Archive + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Images + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Pdf + '')?.setValue(true);
this.libraryForm.get(FileTypeGroup.Epub + '')?.setValue(true);
break;
case LibraryType.Images:
this.libraryForm.get(FileTypeGroup.Archive + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Images + '')?.setValue(true);
this.libraryForm.get(FileTypeGroup.Pdf + '')?.setValue(false);
this.libraryForm.get(FileTypeGroup.Epub + '')?.setValue(false);
}
}),
takeUntilDestroyed(this.destroyRef)
).subscribe();
}
setValues() {
@ -148,8 +197,27 @@ export class LibrarySettingsModalComponent implements OnInit {
this.libraryForm.get('allowScrobbling')?.setValue(this.library.allowScrobbling);
this.selectedFolders = this.library.folders;
this.madeChanges = false;
this.cdRef.markForCheck();
for(let fileTypeGroup of allFileTypeGroup) {
this.libraryForm.addControl(fileTypeGroup + '', new FormControl(this.library.libraryFileTypes.includes(fileTypeGroup), []));
}
for(let glob of this.library.excludePatterns) {
this.libraryForm.addControl('excludeGlob-' , new FormControl(glob, []));
}
} else {
for(let fileTypeGroup of allFileTypeGroup) {
this.libraryForm.addControl(fileTypeGroup + '', new FormControl(true, []));
}
}
this.excludePatterns = this.library.excludePatterns;
if (this.excludePatterns.length === 0) {
this.excludePatterns = [''];
}
this.cdRef.markForCheck();
}
updateGlobs(items: Array<string>) {
this.excludePatterns = items;
this.cdRef.markForCheck();
}
isDisabled() {
@ -172,6 +240,13 @@ export class LibrarySettingsModalComponent implements OnInit {
async save() {
const model = this.libraryForm.value;
model.folders = this.selectedFolders;
model.fileGroupTypes = [];
for(let fileTypeGroup of allFileTypeGroup) {
if (model[fileTypeGroup]) {
model.fileGroupTypes.push(fileTypeGroup);
}
}
model.excludePatterns = this.excludePatterns;
if (this.libraryForm.errors) {
return;