Bulk Operations & Filters
Filter the documents list by status, template, creator, or date. Export selected docs as CSV. Bulk delete or mark as sent/complete.
Bulk Operations & Filters
The Documents list (/app/documents) is built for power users
managing dozens or hundreds of documents at a time. Filters narrow
what you see; bulk actions operate on what you've selected.
Filters
A row of filters above the list lets you slice the workspace's documents:
| Filter | Values | Notes |
|---|---|---|
| Status | All / Draft / Sent / Opened / Completed / Cancelled | Mutually exclusive — uses the same precedence as the dashboard buckets |
| Template | All templates / one of your templates | Find every doc generated from a specific template |
| Creator | All creators / team members who've created docs | Hidden when only one creator exists |
| Sort | Newest / Oldest / Name A–Z / Name Z–A |
Filters compose — pick a status, then a template, then a creator — each narrows the previous result. The total count above the list updates live.
The Search box on the left does a case-insensitive substring match against document name. Combine with the filters for queries like "every Sales contract submitted by Vivek that's still in Draft".
Column customization
Click the Columns dropdown (right of the sort filter) to toggle which optional columns are visible:
| Column | Notes |
|---|---|
| Template | The template name — shown by default |
| Created by | Resolves to the team member's name |
| Created at | Distinct from the always-visible Updated date |
Your selection is persisted per browser under
crove.documents.columns in localStorage, so the layout you
prefer survives reloads.
Quick-view
Hover over a document name in the list (300ms delay so it doesn't fire on cursor sweeps) to see a popover with:
- Full document name
- Created + updated timestamps
- Status badge
- Template name
- Created-by name
Use this to disambiguate similarly-named docs without leaving the list.
Bulk selection
Each row has a checkbox. The header checkbox toggles all visible rows (respects active filters — you can't accidentally select hidden docs). When at least one row is selected, a sticky bulk action bar appears at the top of the list:
| Action | What it does |
|---|---|
| Mark as Sent | Bumps the sent flag — useful for docs delivered out-of-band |
| Mark as Complete | Force-marks complete (skip the normal completion flow) |
| Export CSV | Streams the selected docs as a CSV download (covered below) |
| Delete | Permanently removes selected docs (guarded by AlertDialog) |
| X | Clears selection |
Bulk operations run as Promise.allSettled so a few failures
don't abort the rest. Crove reports partial-failure counts in a
toast at the end.
Bulk download as ZIP
Click Download ZIP in the bulk action bar to stream every selected document's signed PDF inside a single archive.
POST /api/app/documents/download-zip
{ "ids": ["doc_…", "doc_…"] }What you get:
- One PDF per document, named after the document title
(sanitized — non-alphanumeric chars stripped,
(2)/(3)appended on filename collisions) - A
manifest.txtlisting what was included and what was skipped (e.g. docs that don't have a generated PDF yet)
Limits + caveats:
- Cap of 200 documents per ZIP — split into multiple downloads for larger batches
- Documents without a generated PDF are silently skipped (no error, just listed in the manifest as "no PDF generated yet")
- For documents that completed long enough ago, the PDF includes the Certificate of Completion pages by default
The ZIP is generated server-side with jszip so very large
archives stream back as one response — no per-file requests
from the browser.
Saved views
Filter combos are powerful but tedious to recreate. Click the Views button (bookmark icon, next to Columns) to manage named views:
- Save current as view… — pops a prompt for a name, then
stores the current search + status + template + creator + sort
- column visibility under that name
- Click any saved view to switch to it instantly
- Click the trash icon next to a view to delete it
- Reset filters clears all filters back to defaults without affecting saved views
Views are stored client-side under
crove.documents.views in localStorage. They're per-browser, not
per-account — switching workstations means recreating them. This
is intentional: views often contain sensitive filter combos
(e.g. "deals with X teammate over $10k") that shouldn't
auto-share to other devices.
Common patterns:
- "My open work" — Status = Sent + Creator = me
- "Stalled" — Status = Opened, sort by Updated ASC
- "Cancellations to review" — Status = Cancelled, sort by Updated DESC
- "This week's wins" — Status = Completed, sort by Updated DESC
Bulk CSV export
Click Export CSV in the bulk action bar to stream a CSV of the selected documents. The endpoint is:
POST /api/app/documents/export-csv
{ "ids": ["doc_…", "doc_…"] }Cap: 1000 documents per export. The CSV columns are:
| Column | Source |
|---|---|
| Document ID | UUID |
| Document Name | Including any rename via templated completedDocumentName |
| Template | Source template name (joined inline) |
| Status | Same precedence as the UI badges |
| Created At | ISO timestamp |
| Updated At | ISO timestamp |
| Primary Respondent Email | First respondent created |
| Primary Respondent Role | Their role |
| Submitted? | "Yes" / "No" |
| Response JSON | Raw response object stringified |
The Response JSON column gives you everything you need for ad-hoc
analysis in a spreadsheet — load it into Google Sheets and parse
the column with IMPORTJSON or paste into a tool like Hex/Mode.
For exporting all responses for a single template (across every document, not just selected ones), see Per-template CSV export below.
Per-template CSV export
Inside the template editor, the toolbar has a spreadsheet icon that exports every document ever created from that template as a CSV — column headers built from the template's variable names rather than fixed fields:
| Column | Source |
|---|---|
| Document ID | |
| Document Name | |
| Status | |
| Created At | |
<variable_name_1> | response.<varName1> |
<variable_name_2> | response.<varName2> |
… | one column per template variable |
Use this when you want all responses laid out side-by-side. The
endpoint is GET /api/app/templates/{id}/export-csv — it
streams synchronously so it's fast for normal-sized templates.
For very large templates (thousands of documents), the
POST variant queues an Inngest job that emails a presigned
download URL when ready.
Status precedence (matters for filters + exports)
When a doc could match multiple statuses, Crove uses this precedence (highest wins):
cancelled—metadata.cancelledAtis setcompleted—documents.completed === trueopened—documents.opened === truesent—documents.sent === truedraft— none of the above
Same precedence drives the dashboard's 5-bucket stat row, the documents list filter, the bulk export Status column, and the row badges. So whatever you see in the UI is what shows up in the export.
Power-user recipes
- Find stalled docs: Filter Status = Sent, sort by Updated ASC. The top rows have been waiting longest.
- End-of-quarter cleanup: Filter Status = Cancelled, sort Updated ASC. Bulk-select, Delete.
- Audit by creator: Filter Creator =
<teammate>, Status = Completed, Export CSV. Hand to legal. - Template performance: Filter Template =
<one template>, count the Completed vs. Draft buckets — high Draft% = friction in your flow.