Skip to content

Commit

Permalink
feat: add book quotes bayang#124
Browse files Browse the repository at this point in the history
  • Loading branch information
bayang committed Sep 14, 2024
1 parent a0af878 commit 3dbb33d
Show file tree
Hide file tree
Showing 16 changed files with 1,055 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/jelu-ui/src/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@
width: min(600px, 90vw);
}

.quote-modal {
@apply m-5 sm:p-5;
height: min(700px, 75vh);
width: min(900px, 85vw);
}

.review-modal {
@apply m-5 sm:p-5;
height: min(700px, 75vh);
Expand Down
119 changes: 119 additions & 0 deletions src/jelu-ui/src/components/BookDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import ReadingEventModalVue from './ReadingEventModal.vue'
import ReadProgressModal from './ReadProgressModal.vue'
import ReviewCard from "./ReviewCard.vue"
import ReviewModalVue from './ReviewModal.vue'
import BookQuoteModalVue from './BookQuoteModal.vue'
import { BookQuote } from "../model/BookQuote"
import BookQuoteCard from "./BookQuoteCard.vue"
const { t, d } = useI18n({
inheritLocale: true,
Expand Down Expand Up @@ -55,13 +58,16 @@ const getBookIsLoading: Ref<boolean> = ref(false)
const userReviews: Ref<Array<Review>> = ref([])
const bookQuotes: Ref<Array<BookQuote>> = ref([])
const getBook = async () => {
try {
getBookIsLoading.value = true
book.value = await dataService.getUserBookById(props.bookId)
getBookIsLoading.value = false
useTitle('Jelu | ' + book.value.book.title)
getUserReviewsForBook()
getBookQuotesForBook()
} catch (error) {
console.log("failed get book : " + error);
getBookIsLoading.value = false
Expand All @@ -82,6 +88,20 @@ const getUserReviewsForBook = async() => {
})
}
const getBookQuotesForBook = async() => {
await until(user.value).not.toBeNull()
dataService.findBookQuotes(user.value.id, book.value?.book.id, null, 0, 20)
.then(res => {
console.log(res)
if (! res.empty) {
bookQuotes.value = res.content
}
})
.catch(err => {
console.log(err)
})
}
watch(() => props.bookId, (newValue, oldValue) => {
console.log('The new bookId is: ' + props.bookId)
})
Expand Down Expand Up @@ -111,6 +131,11 @@ function reviewModalClosed() {
getUserReviewsForBook()
}
function bookQuoteModalClosed() {
console.log("book quote modal closed")
getBookQuotesForBook()
}
const toggleEdit = () => {
edit.value = !edit.value
oruga.modal.open({
Expand Down Expand Up @@ -162,6 +187,24 @@ function toggleReviewModal(currentBook: Book|undefined, edit: boolean, review: R
}
}
function toggleBookQuoteModal(currentBook: Book|undefined, edit: boolean, bookQuote: BookQuote|null) {
if (currentBook != null && currentBook != undefined) {
oruga.modal.open({
component: BookQuoteModalVue,
trapFocus: true,
active: true,
canCancel: ['x', 'button', 'outside'],
scroll: 'keep',
props: {
"book": currentBook,
"edit" : edit,
"bookQuote": bookQuote
},
onClose: bookQuoteModalClosed
});
}
}
const toggleFetchMetadataModal = (currentBook: Book|undefined) => {
oruga.modal.open({
parent: this,
Expand Down Expand Up @@ -387,6 +430,36 @@ const deleteReview = async (reviewId: string) => {
})
}
const deleteBookQuote = async (bookQuoteId: string) => {
console.log("delete " + bookQuoteId)
let abort = false
await ObjectUtils.swalMixin.fire({
html: `<p>${t('book_quotes.delete_quote')}</p>`,
showCancelButton: true,
showConfirmButton: false,
showDenyButton: true,
confirmButtonText: t('labels.delete'),
cancelButtonText: t('labels.dont_delete'),
denyButtonText: t('labels.delete'),
}).then((result) => {
if (result.isDismissed) {
abort = true
return;
}
})
console.log("abort " + abort)
if (abort) {
return
}
dataService.deleteBookQuote(bookQuoteId)
.then(res => {
getBookQuotesForBook()
})
.catch(err => {
console.log(err)
})
}
getBook()
</script>
Expand Down Expand Up @@ -527,6 +600,28 @@ getBook()
</svg>
</button>
</li>
<li>
<button
v-tooltip="t('labels.add_quote')"
class="btn btn-circle btn-outline border-none"
@click="toggleBookQuoteModal(book?.book, false, null)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-6"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0 1 11.186 0Z"
/>
</svg>
</button>
</li>
</ul>
</div>
</div>
Expand Down Expand Up @@ -766,6 +861,30 @@ getBook()
/>
</div>
</div>
<div
v-if="bookQuotes != null && bookQuotes.length > 0"
class="w-11/12 sm:w-10/12 flex flex-row flex-wrap justify-center mt-4 gap-4"
>
<router-link
class="link text-2xl typewriter"
:to="{ name: 'book-quotes', params: { bookId: book?.book.id } }"
>
{{ t('book_quotes.quote', 2) }}
</router-link>
<div
v-for="quote in bookQuotes"
:key="quote.id"
>
<book-quote-card
v-if="quote != null"
:book-quote="quote"
:show-delete="true"
:show-edit="true"
@update:delete="deleteBookQuote($event)"
@update:edit="toggleBookQuoteModal(book?.book, true, quote)"
/>
</div>
</div>
<!-- https://tailwindcomponents.com/component/vertical-timeline -->
<div
v-if="book?.readingEvents != null && book?.readingEvents?.length > 0"
Expand Down
105 changes: 105 additions & 0 deletions src/jelu-ui/src/components/BookQuoteCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<script setup lang="ts">
import { ref } from "vue";
import { useI18n } from 'vue-i18n';
import { BookQuote } from "../model/BookQuote";
import dataService from "../services/DataService";
const { t, d } = useI18n({
inheritLocale: true,
useScope: 'global'
})
const props = defineProps<{
bookQuote: BookQuote,
showDelete: boolean,
showEdit: boolean,
}>();
const username = ref("")
const getUsername = async () => {
username.value = await dataService.usernameById(props.bookQuote.user)
}
getUsername()
const emit = defineEmits<{
(e: 'update:delete', bookQuoteId: string): void,
(e: 'update:edit', bookQuoteId: string): void,
}>()
const deleteBookQuote = async (bookQuoteId: string) => {
emit("update:delete", bookQuoteId)
}
const editBookQuote = async (bookQuoteId: string) => {
emit("update:edit", bookQuoteId)
}
</script>

<template>
<div
class="card card-compact bg-base-200 shadow-2xl shadow-base-300 p-4"
>
<div class="card-body">
<div class="card-title">
<div class="avatar placeholder">
<div class="bg-[color-mix(in_oklab,oklch(var(--n)),black_7%)] text-neutral-content rounded-full w-12">
<span class="uppercase">{{ username.slice(0,2) }}</span>
</div>
</div>
{{ username }} :
</div>
<div class="ml-7">
<v-md-preview
class="text-justify text-base"
:text="props.bookQuote.text"
/>
</div>
<p class="font-bold font-mono">
{{ bookQuote.position }}
</p>
<div class="card-actions justify-end items-center">
{{ d(props.bookQuote.creationDate, 'short') }}&nbsp;

<button
v-if="props.showEdit"
class="btn btn-outline btn-warning p-2 border-none"
@click="editBookQuote(props.bookQuote.id)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
</svg>
</button>
<button
v-if="props.showDelete"
class="btn btn-outline btn-error p-2 border-none"
@click="deleteBookQuote(props.bookQuote.id)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z"
clip-rule="evenodd"
/>
</svg>
</button>
</div>
</div>
</div>
</template>

<style lang="scss" scoped>
</style>
Loading

0 comments on commit 3dbb33d

Please sign in to comment.