updated history page

This commit is contained in:
Gaumit Kauts
2026-02-15 10:33:57 -07:00
parent a4efc8467f
commit 0162365700
12 changed files with 56 additions and 27 deletions

View File

@@ -868,19 +868,18 @@ def api_delete_post(post_id: int):
return _error("You don't have permission to delete this post.", 403)
try:
add_audit_log({
"user_id": user_id,
"action": "post.deleted",
"details": json.dumps({"deleted_post_id": post_id, "title": post.get("title")})
})
delete_rag_chunks(post_id)
delete_archive_files(post_id)
delete_metadata(post_id)
delete_rights(post_id)
delete_audio_post(post_id)
add_audit_log({
"post_id": post_id,
"user_id": user_id,
"action": "post.deleted",
"details": json.dumps({"title": post.get("title")})
})
return jsonify({"message": "Post deleted successfully", "post_id": post_id})
except Exception as e:

BIN
frontend/public/Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

View File

@@ -61,6 +61,7 @@ export default function App() {
localStorage.removeItem('voicevault_user')
setShowLogin(true)
setActiveTab('feed')
setViewingPostId(null)
}
const handleSearch = async (query) => {
@@ -91,9 +92,15 @@ export default function App() {
setViewingPostId(null)
}
const handleTabChange = (tab) => {
setActiveTab(tab)
setViewingPostId(null)
}
const handlePostCreated = () => {
// Switch to feed after creating a post
setActiveTab('feed')
setViewingPostId(null)
}
const handleUserUpdate = (updatedUser) => {
@@ -202,11 +209,16 @@ export default function App() {
// Main App
return (
<div className="h-screen bg-gray-50 text-gray-800 flex flex-col overflow-hidden">
<div className="h-screen bg-white-50 text-gray-800 flex flex-col overflow-hidden">
<Header onSearch={handleSearch} onLogout={handleLogout} onNavigateToSearch={handleNavigateToSearch} />
<<<<<<< HEAD
<div className="flex-1 flex overflow-hidden max-w-[1400px] mx-auto w-full">
<Sidebar user={user} activeTab={activeTab} onTabChange={handleTabChange} />
=======
<div className="flex-1 flex overflow-hidden max-w-[1500px] mx-auto w-full">
<Sidebar user={user} activeTab={activeTab} onTabChange={setActiveTab} />
>>>>>>> cd657f37cf76773d9dd6ad7a0cdbe05e19a9eced
<main className="flex-1 overflow-y-auto p-6">
{renderPage()}

View File

@@ -27,13 +27,16 @@ class ApiClient {
try {
const response = await fetch(url, config);
const data = await response.json();
const contentType = response.headers.get('content-type') || '';
const isJson = contentType.includes('application/json');
const data = isJson ? await response.json() : null;
if (!response.ok) {
throw new Error(data.error || 'Request failed');
const fallbackError = `Request failed with status ${response.status}`;
throw new Error((data && data.error) || fallbackError);
}
return data;
return data || {};
} catch (error) {
console.error('API Error:', error);
throw error;
@@ -87,14 +90,16 @@ class ApiClient {
method: 'POST',
body: formData, // Don't set Content-Type, let browser set it with boundary
});
const data = await response.json();
const contentType = response.headers.get('content-type') || '';
const isJson = contentType.includes('application/json');
const data = isJson ? await response.json() : null;
if (!response.ok) {
throw new Error(data.error || 'Upload failed');
const fallbackError = `Upload failed with status ${response.status}`;
throw new Error((data && data.error) || fallbackError);
}
return data;
return data || {};
} catch (error) {
console.error('Upload Error:', error);
throw error;
@@ -144,10 +149,6 @@ class ApiClient {
});
}
async getPostMetadata(postId) {
return this.request(`/posts/${postId}/metadata`);
}
async getAudioUrl(postId, expiresIn = 3600) {
return this.request(`/posts/${postId}/audio?expires_in=${expiresIn}`);
}

View File

@@ -28,8 +28,8 @@ export default function EditPostModal({ post, user, onClose, onSave }) {
visibility
}
await api.editPost(post.post_id, updates)
onSave?.()
const updatedPost = await api.editPost(post.post_id, updates)
onSave?.(updatedPost)
onClose()
} catch (err) {
setError(err.message || 'Failed to update post')

View File

@@ -23,10 +23,15 @@ export default function Header({ onSearch, onLogout, onNavigateToSearch }) {
<div className="max-w-[1400px] mx-auto flex items-center justify-between gap-6">
{/* Left: Logo */}
<div className="flex items-center gap-3 flex-shrink-0">
<div className="w-8 h-8 bg-[#f4b840] rounded-lg flex items-center justify-center">
<svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<div className="w-8 h-8 rounded-lg flex items-center justify-center">
{/* <svg className="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" />
</svg>
</svg> */}
<img
src="/Logo.png"
alt="VoiceVault Logo"
className="w-10 h-10 object-contain rounded-lg"
/>
</div>
<h1 className="text-lg font-bold text-gray-900">VoiceVault</h1>
</div>

View File

@@ -40,7 +40,7 @@ export default function History({ user, onViewPost }) {
try {
await api.deletePost(postId, user.user_id)
// Remove from local state immediately
setPosts(posts.filter(p => p.post_id !== postId))
setPosts((prev) => prev.filter((p) => p.post_id !== postId))
} catch (err) {
alert('Failed to delete post: ' + err.message)
} finally {
@@ -58,8 +58,15 @@ export default function History({ user, onViewPost }) {
setEditingPost(post)
}
const handleSaveEdit = () => {
// Refresh the list after edit
const handleSaveEdit = (updatedPost) => {
if (updatedPost && updatedPost.post_id) {
setPosts((prev) =>
prev.map((post) =>
post.post_id === updatedPost.post_id ? { ...post, ...updatedPost } : post
)
)
return
}
fetchHistory()
}

View File

@@ -16,6 +16,7 @@ export default function PostDetail({ postId, user, onBack }) {
const [volume, setVolume] = useState(1)
const [downloading, setDownloading] = useState(false)
const audioRef = useRef(null)
const [audioSrc, setAudioSrc] = useState(null)
useEffect(() => {
if (postId) {
@@ -34,6 +35,8 @@ export default function PostDetail({ postId, user, onBack }) {
// Load audio URL if available
if (postData.audio_url && audioRef.current) {
setPost(postData)
setAudioSrc(postData.audio_url)
audioRef.current.src = postData.audio_url
audioRef.current.load()
}
@@ -290,12 +293,14 @@ export default function PostDetail({ postId, user, onBack }) {
<audio
ref={audioRef}
src={audioSrc}
onTimeUpdate={handleTimeUpdate}
onLoadedMetadata={handleLoadedMetadata}
onEnded={handleEnded}
preload="metadata"
/>
<div className="flex items-center gap-4 mb-4">
<button
onClick={togglePlay}