vault backup: 2026-05-15 16:48:40
This commit is contained in:
parent
1034662429
commit
da166fd29c
4 changed files with 114 additions and 1 deletions
|
|
@ -35,7 +35,7 @@ This 3-hop pattern works for hundreds of articles without vector search.
|
|||
| [[wiki/reports/_index\|reports/]] | Weekly and monthly summaries — generate: `uv run python scripts/report-generator.py --weekly` | 1 |
|
||||
| [[wiki/infrastructure/_index\|infrastructure/]] | Server inventory: all 10 SSH hosts — optical, optical-dev, optical-prod, baic, librechat, modocmms, box-cli, aimpress, pve | 12 |
|
||||
| [[wiki/testing/_index\|testing/]] | Web app testing: functional, performance, security, UI types; TDD/BDD/Agile methodologies; Selenium/Cypress/Playwright/JMeter/OWASP ZAP tools | 1 |
|
||||
| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 139 |
|
||||
| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 140 |
|
||||
|
||||
| [[wiki/shared-patterns/_index\|shared-patterns/]] | Oliver Agency standard library patterns: httpx, structlog, pydantic-settings, alembic — reuse before writing from scratch | 4 |
|
||||
| [[wiki/mistakes/_index\|mistakes/]] | Anti-patterns extracted from sessions — per-stack running lists (fastapi, react, docker, postgres, general) — injected at session start | 5 |
|
||||
|
|
|
|||
|
|
@ -141,3 +141,4 @@
|
|||
| [[wiki/payloadcms/rich-text-official-features\|Rich Text — Official Lexical Features]] | All 24 official features: 19 default-on (bold/italic/heading/lists/links/upload…) + 5 opt-in (FixedToolbar/Blocks/TreeView/Table/TextState); full config reference + TextStateFeature frontend rendering | raw/rich-text__official-features.md | 2026-05-15 |
|
||||
| [[wiki/payloadcms/rich-text-rendering-on-demand\|Rich Text — Rendering On Demand (RenderLexical)]] | `RenderLexical` experimental component: render Lexical editor outside a Form via server action, schemaPath resolution, inside-Form vs controlled-state modes, hidden anchor field tip | raw/rich-text__rendering-on-demand.md | 2026-05-15 |
|
||||
| [[wiki/payloadcms/rich-text-views\|Rich Text — Lexical Views]] | Experimental: named rendering modes (default/preview/branded) for Lexical nodes — shared admin panel + JSX converter rendering, view selector UI, Component/createDOM/html overrides, Block/Label keys, bundle-size gotcha | raw/rich-text__views.md | 2026-05-15 |
|
||||
| [[wiki/payloadcms/trash-soft-delete\|Trash — Soft Delete]] | `trash: true` on a collection enables soft delete via `deletedAt` timestamp; dedicated Trash admin view; `trash` query param for all APIs; access control differentiates trash vs permanent delete via `data.deletedAt` | raw/trash__overview.md | 2026-05-15 |
|
||||
|
|
|
|||
112
wiki/payloadcms/trash-soft-delete.md
Normal file
112
wiki/payloadcms/trash-soft-delete.md
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
title: "Trash — Soft Delete"
|
||||
aliases: [soft-delete, trash, deletedAt, restore-documents]
|
||||
tags: [payloadcms, collections, admin-panel, access-control, api]
|
||||
sources: [raw/trash__overview.md]
|
||||
created: 2026-05-15
|
||||
updated: 2026-05-15
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Trash (soft delete) marks documents as deleted without permanently removing them. Enable it per collection with `trash: true`. Payload injects a `deletedAt` timestamp field automatically.
|
||||
|
||||
```ts
|
||||
export const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
trash: true,
|
||||
fields: [...],
|
||||
}
|
||||
```
|
||||
|
||||
## Admin Panel
|
||||
|
||||
- New route added: `/collections/:collectionSlug/trash`
|
||||
- Trash view shows all documents with a `deletedAt` timestamp
|
||||
- Bulk actions: **Restore**, **Delete** (permanent), **Empty Trash**
|
||||
- Edit view of trashed document: all fields **read-only**; only Restore and Permanently Delete actions available
|
||||
- API / Versions / Preview tabs remain accessible from trashed doc edit view
|
||||
- Main list view delete → soft-deletes by default; checkbox in modal allows skipping trash
|
||||
|
||||
## API — `trash` Parameter
|
||||
|
||||
Applies to: `find`, `findByID`, `update`, `updateByID`, `delete`, `deleteByID`, `findVersions`, `findVersionByID`
|
||||
|
||||
| Goal | Query |
|
||||
|------|-------|
|
||||
| All documents (normal + trashed) | `trash: true` |
|
||||
| Only trashed | `trash: true` + `where: { deletedAt: { exists: true } }` |
|
||||
| Only non-trashed (explicit) | `trash: false` |
|
||||
|
||||
### Local API
|
||||
|
||||
```ts
|
||||
// Only trashed
|
||||
const result = await payload.find({
|
||||
collection: 'posts',
|
||||
trash: true,
|
||||
where: { deletedAt: { exists: true } },
|
||||
})
|
||||
```
|
||||
|
||||
### REST
|
||||
|
||||
```http
|
||||
GET /api/posts?trash=true&where[deletedAt][exists]=true
|
||||
```
|
||||
|
||||
### GraphQL
|
||||
|
||||
```graphql
|
||||
query {
|
||||
Posts(trash: true, where: { deletedAt: { exists: true } }) {
|
||||
docs { id deletedAt }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Access Control
|
||||
|
||||
All trash actions (soft-delete, restore, permanent delete) respect the collection's `delete` access control.
|
||||
|
||||
The `delete` function receives `data`:
|
||||
- **Trashing** → `data.deletedAt` is set to a timestamp
|
||||
- **Permanent delete** → `data` is `undefined`
|
||||
|
||||
### Pattern: editors can trash, only admins can permanently delete
|
||||
|
||||
```ts
|
||||
access: {
|
||||
delete: ({ req: { user }, data }) => {
|
||||
if (!user) return false
|
||||
if (user.roles?.includes('admin')) return true
|
||||
// Allow trash (deletedAt being set), deny permanent delete
|
||||
if (data?.deletedAt) return true
|
||||
return false
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
In the Admin Panel, when a user can trash but not permanently delete:
|
||||
- Delete button is visible
|
||||
- "Delete permanently" checkbox is hidden
|
||||
|
||||
## Versions + Trash Interaction
|
||||
|
||||
- A trashed document **cannot** have a version restored until the document itself is restored from trash
|
||||
- Attempting to restore a version of a trashed document throws an error
|
||||
- Version history is still **visible** from the trashed document's edit view
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- Enable with `trash: true` on the [[wiki/payloadcms/collection-config|Collection Config]]
|
||||
- `deletedAt` field is auto-injected; set on soft-delete, cleared on restore
|
||||
- Default delete from list view = soft delete; checkbox overrides to permanent
|
||||
- `trash: true` query param *includes* trashed docs — combine with `where: { deletedAt: { exists: true } }` to get *only* trashed
|
||||
- [[wiki/payloadcms/access-control|Access Control]] `delete` function can distinguish trash vs permanent via `data.deletedAt`
|
||||
- Must restore document from trash before restoring any of its versions
|
||||
- Similar access control pattern to publish (`data._status`) — use `data` arg to differentiate operations
|
||||
|
||||
## Sources
|
||||
|
||||
- `raw/trash__overview.md` (https://payloadcms.com/docs/trash/overview)
|
||||
Loading…
Add table
Reference in a new issue