mirror of
https://github.com/booklore-app/booklore.git
synced 2026-02-18 00:17:53 +01:00
Add ability to reset reading progress for a book
This commit is contained in:
committed by
Aditya Chandel
parent
5afe0a1b0a
commit
ceac960943
@@ -124,4 +124,11 @@ public class BookController {
|
||||
bookService.updateReadStatus(bookId, request.status());
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@PostMapping("/{bookId}/reset-progress")
|
||||
@CheckBookAccess(bookIdParam = "bookId")
|
||||
public ResponseEntity<Book> resetProgress(@PathVariable long bookId) {
|
||||
Book book = bookService.resetProgress(bookId);
|
||||
return ResponseEntity.ok(book);
|
||||
}
|
||||
}
|
||||
@@ -277,6 +277,24 @@ public class BookService {
|
||||
return book;
|
||||
}
|
||||
|
||||
public Book resetProgress(long bookId) {
|
||||
BookLoreUser user = authenticationService.getAuthenticatedUser();
|
||||
BookEntity bookEntity = bookRepository.findById(bookId).orElseThrow(() -> ApiError.BOOK_NOT_FOUND.createException(bookId));
|
||||
|
||||
UserBookProgressEntity progress = userBookProgressRepository.findByUserIdAndBookId(user.getId(), bookId).orElse(new UserBookProgressEntity());
|
||||
progress.setBook(bookEntity);
|
||||
progress.setReadStatus(null);
|
||||
progress.setLastReadTime(null);
|
||||
progress.setPdfProgress(null);
|
||||
progress.setPdfProgressPercent(null);
|
||||
progress.setEpubProgress(null);
|
||||
progress.setEpubProgressPercent(null);
|
||||
progress.setCbxProgress(null);
|
||||
progress.setCbxProgressPercent(null);
|
||||
userBookProgressRepository.save(progress);
|
||||
return bookMapper.toBook(bookEntity);
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public List<Book> assignShelvesToBooks(Set<Long> bookIds, Set<Long> shelfIdsToAssign, Set<Long> shelfIdsToUnassign) {
|
||||
|
||||
@@ -190,7 +190,28 @@
|
||||
{{ getFileExtension(book?.filePath) || '-' }}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="whitespace-nowrap flex items-center">
|
||||
<span class="font-bold mr-2">Progress:</span>
|
||||
<span class="inline-flex items-center">
|
||||
<span
|
||||
class="inline-block px-2 py-0.5 rounded-full text-xs font-bold text-white"
|
||||
[ngClass]="getProgressColorClass(getProgressPercent(book))">
|
||||
{{ getProgressPercent(book) !== null ? getProgressPercent(book) + '%' : 'N/A' }}
|
||||
</span>
|
||||
@if (getProgressPercent(book) !== null) {
|
||||
<p-button
|
||||
pTooltip="Reset progress"
|
||||
tooltipPosition="bottom"
|
||||
icon="pi pi-refresh"
|
||||
size="small"
|
||||
severity="danger"
|
||||
text
|
||||
class="ml-1"
|
||||
(onClick)="resetProgress(book)">
|
||||
</p-button>
|
||||
}
|
||||
</span>
|
||||
</p>
|
||||
<p class="whitespace-nowrap flex items-center gap-2">
|
||||
<span class="font-bold">Metadata Score:</span>
|
||||
@if (book?.metadataMatchScore != null) {
|
||||
@@ -203,14 +224,6 @@
|
||||
<span>-</span>
|
||||
}
|
||||
</p>
|
||||
<p class="whitespace-nowrap flex items-center gap-2">
|
||||
<span class="font-bold">Progress:</span>
|
||||
<span
|
||||
class="inline-block px-2 py-0.5 rounded-full text-xs font-bold text-white"
|
||||
[ngClass]="getProgressColorClass(getProgressPercent(book))">
|
||||
{{ getProgressPercent(book) !== null ? getProgressPercent(book) + '%' : 'N/A' }}
|
||||
</span>
|
||||
</p>
|
||||
<p class="whitespace-nowrap"><span class="font-bold">File Size:</span> {{ getFileSizeInMB(book) }}</p>
|
||||
<p class="whitespace-nowrap"><span class="font-bold">ISBN 13:</span> {{ book?.metadata!.isbn13 || '-' }}</p>
|
||||
</div>
|
||||
|
||||
@@ -346,14 +346,14 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
return 'bg-blue-500';
|
||||
}
|
||||
|
||||
onPersonalRatingChange(book: Book, { value: personalRating }: RatingRateEvent): void {
|
||||
onPersonalRatingChange(book: Book, {value: personalRating}: RatingRateEvent): void {
|
||||
if (!book?.metadata) return;
|
||||
|
||||
const updatedMetadata = { ...book.metadata, personalRating };
|
||||
const updatedMetadata = {...book.metadata, personalRating};
|
||||
|
||||
this.bookService.updateBookMetadata(book.id, {
|
||||
metadata: updatedMetadata,
|
||||
clearFlags: { personalRating: false }
|
||||
clearFlags: {personalRating: false}
|
||||
}, false).subscribe({
|
||||
next: () => {
|
||||
this.messageService.add({
|
||||
@@ -461,4 +461,35 @@ export class MetadataViewerComponent implements OnInit, OnChanges {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
resetProgress(book: Book): void {
|
||||
this.confirmationService.confirm({
|
||||
message: `Reset reading progress for "${book.metadata?.title}"?`,
|
||||
header: 'Confirm Reset',
|
||||
icon: 'pi pi-exclamation-triangle',
|
||||
acceptLabel: 'Yes',
|
||||
rejectLabel: 'Cancel',
|
||||
acceptButtonStyleClass: 'p-button-danger',
|
||||
accept: () => {
|
||||
this.bookService.resetProgress(book.id).subscribe({
|
||||
next: () => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Progress Reset',
|
||||
detail: 'Reading progress has been reset.',
|
||||
life: 1500
|
||||
});
|
||||
},
|
||||
error: () => {
|
||||
this.messageService.add({
|
||||
severity: 'error',
|
||||
summary: 'Failed',
|
||||
detail: 'Could not reset progress.',
|
||||
life: 1500
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,6 +397,12 @@ export class BookService {
|
||||
);
|
||||
}
|
||||
|
||||
resetProgress(bookId: number): Observable<Book> {
|
||||
return this.http.post<Book>(`${this.url}/${bookId}/reset-progress`, null).pipe(
|
||||
tap(updatedBook => this.handleBookUpdate(updatedBook))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/*------------------ All the websocket handlers go below ------------------*/
|
||||
|
||||
@@ -436,7 +442,7 @@ export class BookService {
|
||||
updatedMap.has(book.id) ? updatedMap.get(book.id)! : book
|
||||
);
|
||||
|
||||
this.bookStateSubject.next({ ...currentState, books: mergedBooks });
|
||||
this.bookStateSubject.next({...currentState, books: mergedBooks});
|
||||
}
|
||||
|
||||
handleBookMetadataUpdate(bookId: number, updatedMetadata: BookMetadata) {
|
||||
|
||||
Reference in New Issue
Block a user