Add trust features: history, trash, export, and collection sharing
release gate / check (push) Failing after 6m36s
release gate / check (push) Failing after 6m36s
Implement Notion-like upgrade phase 4: append-only page revisions with restore-as-a-new-version; recoverable bookmark/page/collection deletions whose restores never resurrect public flags or shares; owner-scoped JSON export; and explicit, revocable read-only collection sharing with owner-only mutations and no transitive third-party bookmark leaks. Add migration 009, API/docs, integration coverage, and page/collections/trash UI.
This commit is contained in:
@@ -176,7 +176,7 @@ export function BookmarksClient({ initialSearch = null, initialOpen = null }: {
|
||||
<div className="flex gap-1" onClick={(e: React.MouseEvent) => e.stopPropagation()}>
|
||||
<a href={b.url} target="_blank" rel="noopener noreferrer"><ExternalLink className="h-4 w-4 text-muted-foreground hover:text-primary" /></a>
|
||||
{tab === 'mine' && (
|
||||
<button onClick={async () => { if (!confirm('Delete?')) return; try { const res = await fetch(`/api/bookmarks/${b.id}`, { method: 'DELETE' }); if (res.ok) { toast.success('Deleted'); load() } else toast.error('Could not delete bookmark') } catch { toast.error('Could not delete bookmark') } }}><Trash2 className="h-4 w-4 text-muted-foreground hover:text-destructive" /></button>
|
||||
<button onClick={async () => { if (!confirm('Move this bookmark to the trash? It can be restored.')) return; try { const res = await fetch(`/api/bookmarks/${b.id}`, { method: 'DELETE' }); if (res.ok) { toast.success('Moved to trash'); load() } else toast.error('Could not move bookmark to trash') } catch { toast.error('Could not move bookmark to trash') } }}><Trash2 className="h-4 w-4 text-muted-foreground hover:text-destructive" /></button>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
Reference in New Issue
Block a user