mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-06-04 22:25:36 -04:00
* Started designing the backend localization service * Worked in Transloco for initial PoC * Worked in Transloco for initial PoC * Translated the login screen * translated dashboard screen * Started work on the backend * Fixed a logic bug * translated edit-user screen * Hooked up the backend for having a locale property. * Hooked up the ability to view the available locales and switch to them. * Made the localization service languages be derived from what's in langs/ directory. * Fixed up localization switching * Switched when we check for a license on UI bootstrap * Tweaked some code * Fixed the bug where dashboard wasn't loading and made it so language switching is working. * Fixed a bug on dashboard with languagePath * Converted user-scrobble-history.component.html * Converted spoiler.component.html * Converted review-series-modal.component.html * Converted review-card-modal.component.html * Updated the readme * Translated using Weblate (English) Currently translated at 100.0% (54 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/en/ * Converted review-card.component.html * Deleted dead component * Converted want-to-read.component.html * Added translation using Weblate (Korean) * Translated using Weblate (Spanish) Currently translated at 40.7% (22 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/es/ * Translated using Weblate (Korean) Currently translated at 62.9% (34 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/ko/ * Converted user-preferences.component.html * Translated using Weblate (Korean) Currently translated at 92.5% (50 of 54 strings) Translation: Kavita/ui Translate-URL: https://hosted.weblate.org/projects/kavita/ui/ko/ * Converted user-holds.component.html * Converted theme-manager.component.html * Converted restriction-selector.component.html * Converted manage-devices.component.html * Converted edit-device.component.html * Converted change-password.component.html * Converted change-email.component.html * Converted change-age-restriction.component.html * Converted api-key.component.html * Converted anilist-key.component.html * Converted typeahead.component.html * Converted user-stats-info-cards.component.html * Converted user-stats.component.html * Converted top-readers.component.html * Converted some pipes and ensure translation is loaded before the app. * Finished all but one pipe for localization * Converted directory-picker.component.html * Converted library-access-modal.component.html * Converted a few components * Converted a few components * Converted a few components * Converted a few components * Converted a few components * Merged weblate in * ... -> … update * Updated the readme * Updateded all fonts to be woff2 * Cleaned up some strings to increase re-use * Removed an old flow (that doesn't exist in backend any longer) from when we introduced emails on Kavita. * Converted Series detail * Lots more converted * Lots more converted & hooked up the ability to flatten during prod build the language files. * Lots more converted * Lots more converted & fixed a bunch of broken pipes due to inject() * Lots more converted * Lots more converted * Lots more converted & fixed some bad keys * Lots more converted * Fixed some bugs with admin dasbhoard nested tabs not rendering on first load due to not using onpush change detection * Fixed up some localization errors and fixed forgot password error when the user doesn't have change password permission * Fixed a stupid build issue again * Started adding errors for interceptor and backend. * Finished off manga-reader * More translations * Few fixes * Fixed a bug where character tag badges weren't showing the name on chapter info * All components are translated * All toasts are translated * All confirm/alerts are translated * Trying something new for the backend * Migrated the localization strings for the backend into a new file. * Updated the localization service to be able to do backend localization with fallback to english. * Cleaned up some external reviews code to reduce looping * Localized AccountController.cs * 60% done with controllers * All controllers are done * All KavitaExceptions are covered * Some shakeout fixes * Prep for initial merge * Everything is done except options and basic shakeout proves response times are good. Unit tests are broken. * Fixed up the unit tests * All unit tests are now working * Removed some quantifier * I'm not sure I can support localization for some Volume/Chapter/Book strings within the codebase. --------- Co-authored-by: Robbie Davis <robbie@therobbiedavis.com> Co-authored-by: majora2007 <kavitareader@gmail.com> Co-authored-by: expertjun <jtrobin@naver.com> Co-authored-by: ThePromidius <thepromidiusyt@gmail.com>
138 lines
5.7 KiB
TypeScript
138 lines
5.7 KiB
TypeScript
import {
|
|
ChangeDetectionStrategy,
|
|
ChangeDetectorRef,
|
|
Component,
|
|
DestroyRef,
|
|
inject,
|
|
OnInit
|
|
} from '@angular/core';
|
|
import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
|
|
import { ToastrService } from 'ngx-toastr';
|
|
import { distinctUntilChanged, filter, take } from 'rxjs/operators';
|
|
import { ConfirmService } from 'src/app/shared/confirm.service';
|
|
import { LibrarySettingsModalComponent } from 'src/app/sidenav/_modals/library-settings-modal/library-settings-modal.component';
|
|
import { NotificationProgressEvent } from 'src/app/_models/events/notification-progress-event';
|
|
import { ScanSeriesEvent } from 'src/app/_models/events/scan-series-event';
|
|
import { Library } from 'src/app/_models/library';
|
|
import { LibraryService } from 'src/app/_services/library.service';
|
|
import { EVENTS, Message, MessageHubService } from 'src/app/_services/message-hub.service';
|
|
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
|
import { SentenceCasePipe } from '../../pipe/sentence-case.pipe';
|
|
import { TimeAgoPipe } from '../../pipe/time-ago.pipe';
|
|
import { LibraryTypePipe } from '../../pipe/library-type.pipe';
|
|
import { RouterLink } from '@angular/router';
|
|
import { NgFor, NgIf } from '@angular/common';
|
|
import {translate, TranslocoModule} from "@ngneat/transloco";
|
|
import {DefaultDatePipe} from "../../pipe/default-date.pipe";
|
|
|
|
@Component({
|
|
selector: 'app-manage-library',
|
|
templateUrl: './manage-library.component.html',
|
|
styleUrls: ['./manage-library.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
standalone: true,
|
|
imports: [NgFor, RouterLink, NgbTooltip, NgIf, LibraryTypePipe, TimeAgoPipe, SentenceCasePipe, TranslocoModule, DefaultDatePipe]
|
|
})
|
|
export class ManageLibraryComponent implements OnInit {
|
|
|
|
libraries: Library[] = [];
|
|
loading = false;
|
|
/**
|
|
* If a deletion is in progress for a library
|
|
*/
|
|
deletionInProgress: boolean = false;
|
|
libraryTrackBy = (index: number, item: Library) => `${item.name}_${item.lastScanned}_${item.type}_${item.folders.length}`;
|
|
private readonly destroyRef = inject(DestroyRef);
|
|
|
|
constructor(private modalService: NgbModal, private libraryService: LibraryService,
|
|
private toastr: ToastrService, private confirmService: ConfirmService,
|
|
private hubService: MessageHubService, private readonly cdRef: ChangeDetectorRef) { }
|
|
|
|
ngOnInit(): void {
|
|
this.getLibraries();
|
|
|
|
// when a progress event comes in, show it on the UI next to library
|
|
this.hubService.messages$.pipe(takeUntilDestroyed(this.destroyRef),
|
|
filter(event => event.event === EVENTS.ScanSeries || event.event === EVENTS.NotificationProgress),
|
|
distinctUntilChanged((prev: Message<ScanSeriesEvent | NotificationProgressEvent>, curr: Message<ScanSeriesEvent | NotificationProgressEvent>) =>
|
|
this.hasMessageChanged(prev, curr)))
|
|
.subscribe((event: Message<ScanSeriesEvent | NotificationProgressEvent>) => {
|
|
let libId = 0;
|
|
if (event.event === EVENTS.ScanSeries) {
|
|
libId = (event.payload as ScanSeriesEvent).libraryId;
|
|
} else {
|
|
if ((event.payload as NotificationProgressEvent).body.hasOwnProperty('libraryId')) {
|
|
libId = (event.payload as NotificationProgressEvent).body.libraryId;
|
|
}
|
|
}
|
|
|
|
this.libraryService.getLibraries().pipe(take(1)).subscribe(libraries => {
|
|
const newLibrary = libraries.find(lib => lib.id === libId);
|
|
const existingLibrary = this.libraries.find(lib => lib.id === libId);
|
|
if (existingLibrary !== undefined) {
|
|
existingLibrary.lastScanned = newLibrary?.lastScanned || existingLibrary.lastScanned;
|
|
this.cdRef.markForCheck();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
hasMessageChanged(prev: Message<ScanSeriesEvent | NotificationProgressEvent>, curr: Message<ScanSeriesEvent | NotificationProgressEvent>) {
|
|
if (curr.event !== prev.event) return true;
|
|
if (curr.event === EVENTS.ScanSeries) {
|
|
return (prev.payload as ScanSeriesEvent).libraryId === (curr.payload as ScanSeriesEvent).libraryId;
|
|
}
|
|
if (curr.event === EVENTS.NotificationProgress) {
|
|
return (prev.payload as NotificationProgressEvent).eventType != (curr.payload as NotificationProgressEvent).eventType;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
getLibraries() {
|
|
this.loading = true;
|
|
this.cdRef.markForCheck();
|
|
this.libraryService.getLibraries().pipe(take(1), takeUntilDestroyed(this.destroyRef)).subscribe(libraries => {
|
|
this.libraries = [...libraries];
|
|
this.loading = false;
|
|
this.cdRef.markForCheck();
|
|
});
|
|
}
|
|
|
|
editLibrary(library: Library) {
|
|
const modalRef = this.modalService.open(LibrarySettingsModalComponent, { size: 'xl' });
|
|
modalRef.componentInstance.library = library;
|
|
modalRef.closed.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(refresh => {
|
|
if (refresh) {
|
|
this.getLibraries();
|
|
}
|
|
});
|
|
}
|
|
|
|
addLibrary() {
|
|
const modalRef = this.modalService.open(LibrarySettingsModalComponent, { size: 'xl' });
|
|
modalRef.closed.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(refresh => {
|
|
if (refresh) {
|
|
this.getLibraries();
|
|
}
|
|
});
|
|
}
|
|
|
|
async deleteLibrary(library: Library) {
|
|
if (await this.confirmService.confirm(translate('toast.confirm-library-delete', {name: library.name}))) {
|
|
this.deletionInProgress = true;
|
|
this.libraryService.delete(library.id).pipe(take(1)).subscribe(() => {
|
|
this.deletionInProgress = false;
|
|
this.cdRef.markForCheck();
|
|
this.getLibraries();
|
|
this.toastr.success(translate('toasts.library-deleted', {name: library.name}));
|
|
});
|
|
}
|
|
}
|
|
|
|
scanLibrary(library: Library) {
|
|
this.libraryService.scan(library.id).pipe(take(1)).subscribe(() => {
|
|
this.toastr.info(translate('toasts.scan-queued', {name: library.name}));
|
|
});
|
|
}
|
|
}
|