Add thai support in summary
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
Read
|
||||
</router-link>
|
||||
<button
|
||||
v-if="book.status === 'READY'"
|
||||
v-if="book.status === 'READY' && uploadEnabled"
|
||||
class="btn btn-secondary"
|
||||
:disabled="enrichRunning"
|
||||
@click="handleEnrich"
|
||||
@@ -73,6 +73,7 @@
|
||||
import { computed, onUnmounted, ref } from 'vue'
|
||||
import type { Book, EnrichmentProgress } from '@/stores/bookStore'
|
||||
import { useBookStore } from '@/stores/bookStore'
|
||||
import { env } from '@/env';
|
||||
|
||||
const props = defineProps<{
|
||||
book: Book
|
||||
@@ -90,6 +91,7 @@ const enrichFeedback = ref<string | null>(null)
|
||||
let pollTimer: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
const enrichRunning = computed(() => enrichProgress.value?.status === 'RUNNING')
|
||||
const uploadEnabled = env('VITE_UPLOAD_ENABLED') !== 'false'
|
||||
|
||||
async function handleEnrich() {
|
||||
enrichFeedback.value = null
|
||||
|
||||
@@ -120,13 +120,17 @@ export const useTopicStore = defineStore('topics', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function generateSummary(topicId: string): Promise<TopicSummary | null> {
|
||||
async function generateSummary(topicId: string, language: 'en' | 'th' = 'en'): Promise<TopicSummary | null> {
|
||||
summaryLoading.value = true
|
||||
activeSummaryTopicId.value = topicId
|
||||
activeSummary.value = null
|
||||
error.value = null
|
||||
try {
|
||||
const response = await api.post<TopicSummary>(`/topics/${topicId}/summary`)
|
||||
const response = await api.post<TopicSummary>(
|
||||
`/topics/${topicId}/summary`,
|
||||
null,
|
||||
{ params: { language } }
|
||||
)
|
||||
activeSummary.value = response.data
|
||||
return response.data
|
||||
} catch (err: any) {
|
||||
@@ -168,12 +172,16 @@ export const useTopicStore = defineStore('topics', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function generateConceptReport(topicId: string): Promise<ConceptReport | null> {
|
||||
async function generateConceptReport(topicId: string, language: 'en' | 'th' = 'en'): Promise<ConceptReport | null> {
|
||||
conceptReportLoading.value = true
|
||||
activeConceptReport.value = null
|
||||
error.value = null
|
||||
try {
|
||||
const response = await api.post<ConceptReport>(`/topics/${topicId}/concept-reports`)
|
||||
const response = await api.post<ConceptReport>(
|
||||
`/topics/${topicId}/concept-reports`,
|
||||
null,
|
||||
{ params: { language } }
|
||||
)
|
||||
activeConceptReport.value = response.data
|
||||
return response.data
|
||||
} catch (err: any) {
|
||||
|
||||
@@ -38,10 +38,28 @@
|
||||
<div v-if="selectedTopicId && mode === 'summary'" class="history-panel card">
|
||||
<div class="history-header">
|
||||
<span class="history-title">Saved summaries</span>
|
||||
<button class="btn btn-primary btn-sm" :disabled="topicStore.summaryLoading" @click="handleGenerate(selectedTopicId!)">
|
||||
<span v-if="topicStore.summaryLoading" class="spinner" style="width:14px;height:14px;display:inline-block;vertical-align:middle;margin-right:4px;"></span>
|
||||
Generate New
|
||||
</button>
|
||||
<div class="history-actions">
|
||||
<div class="lang-toggle" role="group" aria-label="Summary language">
|
||||
<button
|
||||
type="button"
|
||||
class="lang-toggle-btn"
|
||||
:class="{ 'lang-toggle-btn--active': summaryLanguage === 'en' }"
|
||||
:disabled="topicStore.summaryLoading"
|
||||
@click="summaryLanguage = 'en'"
|
||||
>EN</button>
|
||||
<button
|
||||
type="button"
|
||||
class="lang-toggle-btn"
|
||||
:class="{ 'lang-toggle-btn--active': summaryLanguage === 'th' }"
|
||||
:disabled="topicStore.summaryLoading"
|
||||
@click="summaryLanguage = 'th'"
|
||||
>TH</button>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm" :disabled="topicStore.summaryLoading" @click="handleGenerate(selectedTopicId!)">
|
||||
<span v-if="topicStore.summaryLoading" class="spinner" style="width:14px;height:14px;display:inline-block;vertical-align:middle;margin-right:4px;"></span>
|
||||
Generate New
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="topicStore.summaryListLoading" class="history-loading">
|
||||
@@ -71,10 +89,28 @@
|
||||
<div v-if="selectedTopicId && mode === 'concept'" class="history-panel card">
|
||||
<div class="history-header">
|
||||
<span class="history-title">Saved concept reports</span>
|
||||
<button class="btn btn-primary btn-sm" :disabled="topicStore.conceptReportLoading" @click="handleGenerateConcept(selectedTopicId!)">
|
||||
<span v-if="topicStore.conceptReportLoading" class="spinner" style="width:14px;height:14px;display:inline-block;vertical-align:middle;margin-right:4px;"></span>
|
||||
Generate New
|
||||
</button>
|
||||
<div class="history-actions">
|
||||
<div class="lang-toggle" role="group" aria-label="Report language">
|
||||
<button
|
||||
type="button"
|
||||
class="lang-toggle-btn"
|
||||
:class="{ 'lang-toggle-btn--active': conceptLanguage === 'en' }"
|
||||
:disabled="topicStore.conceptReportLoading"
|
||||
@click="conceptLanguage = 'en'"
|
||||
>EN</button>
|
||||
<button
|
||||
type="button"
|
||||
class="lang-toggle-btn"
|
||||
:class="{ 'lang-toggle-btn--active': conceptLanguage === 'th' }"
|
||||
:disabled="topicStore.conceptReportLoading"
|
||||
@click="conceptLanguage = 'th'"
|
||||
>TH</button>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-sm" :disabled="topicStore.conceptReportLoading" @click="handleGenerateConcept(selectedTopicId!)">
|
||||
<span v-if="topicStore.conceptReportLoading" class="spinner" style="width:14px;height:14px;display:inline-block;vertical-align:middle;margin-right:4px;"></span>
|
||||
Generate New
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="topicStore.conceptReportListLoading" class="history-loading">
|
||||
@@ -269,6 +305,8 @@ const showSources = ref(true)
|
||||
const summaryError = ref<string | null>(null)
|
||||
const conceptError = ref<string | null>(null)
|
||||
const isNoBooks = ref(false)
|
||||
const conceptLanguage = ref<'en' | 'th'>('en')
|
||||
const summaryLanguage = ref<'en' | 'th'>('en')
|
||||
const sourcesSection = ref<HTMLElement | null>(null)
|
||||
const selectedTopicId = ref<string | null>(null)
|
||||
const mode = ref<'summary' | 'concept'>('summary')
|
||||
@@ -401,7 +439,7 @@ async function handleGenerateConcept(topicId: string) {
|
||||
conceptError.value = null
|
||||
isNoBooks.value = false
|
||||
showSources.value = true
|
||||
const result = await topicStore.generateConceptReport(topicId)
|
||||
const result = await topicStore.generateConceptReport(topicId, conceptLanguage.value)
|
||||
if (!result) {
|
||||
conceptError.value = topicStore.error ?? 'Failed to generate concept report.'
|
||||
isNoBooks.value =
|
||||
@@ -425,7 +463,7 @@ async function handleGenerate(topicId: string) {
|
||||
isNoBooks.value = false
|
||||
showSources.value = true
|
||||
|
||||
const result = await topicStore.generateSummary(topicId)
|
||||
const result = await topicStore.generateSummary(topicId, summaryLanguage.value)
|
||||
if (!result) {
|
||||
summaryError.value = topicStore.error ?? 'Failed to generate summary.'
|
||||
isNoBooks.value =
|
||||
@@ -528,6 +566,52 @@ function formatDateShort(iso: string): string {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.history-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.lang-toggle {
|
||||
display: inline-flex;
|
||||
border: 1px solid var(--border-color, #d0d7de);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.lang-toggle-btn {
|
||||
padding: 0.25rem 0.55rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
background: transparent;
|
||||
color: var(--text-secondary, #57606a);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.lang-toggle-btn:not(:last-child) {
|
||||
border-right: 1px solid var(--border-color, #d0d7de);
|
||||
}
|
||||
|
||||
.lang-toggle-btn:hover:not(:disabled) {
|
||||
background: var(--hover-bg, #f3f4f6);
|
||||
}
|
||||
|
||||
.lang-toggle-btn--active {
|
||||
background: var(--primary-color, #0969da);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.lang-toggle-btn--active:hover:not(:disabled) {
|
||||
background: var(--primary-color, #0969da);
|
||||
}
|
||||
|
||||
.lang-toggle-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user