feat(phase-4-09): create new components — FolderRow, FolderBreadcrumb, FolderDeleteModal, ShareModal, DocumentPreviewModal, SearchBar, SortControls, AuditLogTab

- FolderRow: inline rename, three-dot menu, delete/rename callbacks, outside-click close
- FolderBreadcrumb: truncation at depth > 4, nav aria-label, ol structure
- FolderDeleteModal: role=dialog, warning icon, doc count in body, Keep/Delete buttons
- ShareModal: handle input, recipients list with revoke, 404/409 error handling
- DocumentPreviewModal: iframe with proxy URL only (never presigned), Escape/overlay close
- SearchBar: role=search, aria-label, Escape clears
- SortControls: aria-pressed, direction indicator, toggle vs switch logic
- AuditLogTab: filters, paginated table, CSV export via window.location.href
- api/client.js: add adminListAuditLog function
This commit is contained in:
curo1305
2026-05-25 22:10:23 +02:00
parent 437c9d134b
commit 36721575a5
9 changed files with 845 additions and 0 deletions
@@ -0,0 +1,81 @@
<template>
<!-- Overlay -->
<div
class="fixed inset-0 bg-black/40 flex items-center justify-center z-50"
@click.self="handleCancel"
>
<!-- Panel -->
<div
role="dialog"
aria-modal="true"
aria-labelledby="delete-modal-title"
class="bg-white rounded-2xl shadow-xl p-6 max-w-md w-full mx-4"
>
<!-- Warning icon -->
<div class="flex justify-center">
<div class="w-10 h-10 bg-red-50 rounded-full flex items-center justify-center">
<svg class="w-5 h-5 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 9v2m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
</svg>
</div>
</div>
<!-- Heading -->
<h2 id="delete-modal-title" class="text-lg font-semibold text-gray-900 mt-4 text-center">
Delete folder?
</h2>
<!-- Body -->
<p class="text-sm text-gray-600 text-center mt-2 mb-6">
This folder contains {{ folder.doc_count ?? 0 }} document{{ (folder.doc_count ?? 0) !== 1 ? 's' : '' }}.
Deleting it will permanently delete all documents inside. This cannot be undone.
</p>
<!-- Buttons -->
<div class="flex gap-3 justify-end">
<button
@click="handleCancel"
class="text-sm text-gray-600 hover:text-gray-800 px-4 py-2 rounded-lg border border-gray-200 hover:bg-gray-50 transition-colors"
>
Keep folder
</button>
<button
@click="handleConfirm"
class="bg-red-600 hover:bg-red-700 text-white text-sm font-semibold px-4 py-2 rounded-lg min-h-[44px] transition-colors"
>
Delete folder and documents
</button>
</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
folder: {
type: Object,
required: true,
},
onConfirm: {
type: Function,
default: null,
},
onCancel: {
type: Function,
default: null,
},
})
const emit = defineEmits(['confirm', 'cancel'])
function handleConfirm() {
emit('confirm')
if (props.onConfirm) props.onConfirm()
}
function handleCancel() {
emit('cancel')
if (props.onCancel) props.onCancel()
}
</script>