fix deletion of assets on delete ref and delete proj
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type AnyNodeId,
|
type AnyNodeId,
|
||||||
type GuideNode,
|
type GuideNode,
|
||||||
@@ -133,19 +135,25 @@ export function ReferencesDialog({ levelId, open, onOpenChange }: ReferencesDial
|
|||||||
)
|
)
|
||||||
|
|
||||||
const handleDelete = useCallback(
|
const handleDelete = useCallback(
|
||||||
(nodeId: string) => {
|
async (nodeId: string) => {
|
||||||
const refNode = nodes[nodeId as AnyNodeId] as ScanNode | GuideNode | undefined
|
const refNode = nodes[nodeId as AnyNodeId] as ScanNode | GuideNode | undefined
|
||||||
deleteNode(nodeId as AnyNodeId)
|
|
||||||
// Fire-and-forget storage cleanup for Supabase-hosted assets
|
|
||||||
const projectId = activeProject?.id
|
const projectId = activeProject?.id
|
||||||
|
|
||||||
|
// Delete storage asset first (before removing from scene)
|
||||||
if (
|
if (
|
||||||
projectId &&
|
projectId &&
|
||||||
!projectId.startsWith('local_') &&
|
!projectId.startsWith('local_') &&
|
||||||
refNode?.url &&
|
refNode?.url &&
|
||||||
refNode.url.startsWith('https://')
|
(refNode.url.startsWith('http://') || refNode.url.startsWith('https://'))
|
||||||
) {
|
) {
|
||||||
deleteProjectAssetByUrl(projectId, refNode.url).catch(console.error)
|
const result = await deleteProjectAssetByUrl(projectId, refNode.url)
|
||||||
|
if (!result.success) {
|
||||||
|
setUploadError(`Failed to delete asset: ${result.error}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteNode(nodeId as AnyNodeId)
|
||||||
},
|
},
|
||||||
[deleteNode, nodes, activeProject],
|
[deleteNode, nodes, activeProject],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -130,29 +130,29 @@ export async function deleteProjectAssetByUrl(
|
|||||||
return { success: false, error: 'Not authorized' }
|
return { success: false, error: 'Not authorized' }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look up the asset row by url + projectId
|
// Derive storage_key from the public URL
|
||||||
const { data: asset, error: fetchError } = await (supabase.from('project_assets') as any)
|
// URL format: https://<project>.supabase.co/storage/v1/object/public/project-assets/<storageKey>
|
||||||
.select('id, storage_key')
|
const storageKeyFromUrl = url.split(`/${BUCKET}/`)[1]?.split('?')[0]
|
||||||
.eq('project_id', projectId)
|
|
||||||
.eq('url', url)
|
|
||||||
.maybeSingle()
|
|
||||||
|
|
||||||
if (fetchError) {
|
if (!storageKeyFromUrl) {
|
||||||
return { success: false, error: fetchError.message }
|
return { success: false, error: 'Could not derive storage key from URL' }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!asset) {
|
// Delete from storage directly — remove() is a no-op if the file doesn't exist
|
||||||
// Nothing to delete — treat as success
|
const { error: storageError } = await supabase.storage.from(BUCKET).remove([storageKeyFromUrl])
|
||||||
return { success: true }
|
if (storageError) {
|
||||||
|
return { success: false, error: `Storage delete failed: ${storageError.message}` }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from storage
|
// Delete DB row by storage_key scoped to this project
|
||||||
await supabase.storage.from(BUCKET).remove([(asset as any).storage_key])
|
const { error: dbError } = await (supabase.from('project_assets') as any)
|
||||||
|
|
||||||
// Delete row
|
|
||||||
await (supabase.from('project_assets') as any)
|
|
||||||
.delete()
|
.delete()
|
||||||
.eq('id', (asset as any).id)
|
.eq('project_id', projectId)
|
||||||
|
.eq('storage_key', storageKeyFromUrl)
|
||||||
|
|
||||||
|
if (dbError) {
|
||||||
|
return { success: false, error: `DB delete failed: ${dbError.message}` }
|
||||||
|
}
|
||||||
|
|
||||||
return { success: true }
|
return { success: true }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user