feat(phase-4-09): wire components into views — sidebar, cards, home, folder, shared, settings, admin
- AppSidebar: add 'Shared with me' entry (purple icon, count badge) and Folders section with New folder CTA - DocumentCard: add group class, hover-reveal share button, ShareModal v-if, shared indicator pill - HomeView: add SearchBar + SortControls above document list; fetchFolders on mount - FolderView: new view with FolderBreadcrumb, FolderRow list, inline new-subfolder input, document list - SharedView: new view fetching /api/shares/received with owner_handle display and empty state - DocumentView: add PDF preview logic (in_app=DocumentPreviewModal, new_tab=window.open); load preferences on mount - SettingsView: add Document Preferences card with pdf_open_mode radio buttons, auto-save on change - AdminView: add Audit Log tab alongside Users/Quotas/AI Config tabs
This commit is contained in:
@@ -17,10 +17,20 @@
|
||||
Uploaded {{ formatDate(doc.created_at) }} · {{ formatSize(doc.size_bytes) }} · {{ doc.mime_type }}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@click="confirmDelete"
|
||||
class="text-sm text-red-500 hover:text-red-700 shrink-0"
|
||||
>Delete</button>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<!-- Open/Preview button for PDFs -->
|
||||
<button
|
||||
v-if="isPdf"
|
||||
@click="openPdf"
|
||||
class="text-sm px-3 py-1.5 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors"
|
||||
>
|
||||
{{ pdfOpenMode === 'in_app' ? 'Preview' : 'Open' }}
|
||||
</button>
|
||||
<button
|
||||
@click="confirmDelete"
|
||||
class="text-sm text-red-500 hover:text-red-700"
|
||||
>Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Topics -->
|
||||
@@ -91,13 +101,21 @@
|
||||
<pre class="text-xs text-gray-600 whitespace-pre-wrap font-mono bg-gray-50 rounded-lg p-4 max-h-96 overflow-y-auto">{{ doc.extracted_text || '(no text extracted)' }}</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- PDF in-app preview modal -->
|
||||
<DocumentPreviewModal
|
||||
v-if="showPreviewModal && doc"
|
||||
:doc="doc"
|
||||
@close="showPreviewModal = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import TopicBadge from '../components/topics/TopicBadge.vue'
|
||||
import DocumentPreviewModal from '../components/documents/DocumentPreviewModal.vue'
|
||||
import { useDocumentsStore } from '../stores/documents.js'
|
||||
import { useTopicsStore } from '../stores/topics.js'
|
||||
import * as api from '../api/client.js'
|
||||
@@ -114,6 +132,15 @@ const suggesting = ref(false)
|
||||
const classifyError = ref(null)
|
||||
const suggestions = ref([])
|
||||
const selectedSuggestions = ref([])
|
||||
const showPreviewModal = ref(false)
|
||||
const pdfOpenMode = ref('new_tab')
|
||||
|
||||
const isPdf = computed(() => {
|
||||
if (!doc.value) return false
|
||||
const mime = doc.value.mime_type || ''
|
||||
const name = doc.value.original_name || ''
|
||||
return mime === 'application/pdf' || name.toLowerCase().endsWith('.pdf')
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
@@ -121,8 +148,23 @@ onMounted(async () => {
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
// Load user preferences for PDF open mode
|
||||
try {
|
||||
const prefs = await api.getMyPreferences()
|
||||
pdfOpenMode.value = prefs.pdf_open_mode || 'new_tab'
|
||||
} catch {
|
||||
pdfOpenMode.value = 'new_tab'
|
||||
}
|
||||
})
|
||||
|
||||
function openPdf() {
|
||||
if (pdfOpenMode.value === 'in_app') {
|
||||
showPreviewModal.value = true
|
||||
} else {
|
||||
window.open(api.getDocumentContentUrl(doc.value.id), '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
function topicColor(name) {
|
||||
return topicsStore.topics.find(t => t.name === name)?.color ?? '#6366f1'
|
||||
}
|
||||
@@ -166,7 +208,7 @@ async function createSelectedTopics() {
|
||||
|
||||
async function confirmDelete() {
|
||||
if (!confirm(`Delete "${doc.value.original_name}"?`)) return
|
||||
await api.deleteDocument(doc.value.id)
|
||||
await docsStore.remove(doc.value.id)
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user