convex-cms 0.0.5-alpha.3 → 0.0.5-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -12
- package/admin/src/components/BulkActionBar.tsx +4 -4
- package/admin/src/components/ContentEntryEditor.tsx +8 -28
- package/admin/src/components/ContentTypeFormModal.tsx +2 -2
- package/admin/src/components/Sidebar.tsx +150 -58
- package/admin/src/components/TaxonomyEditor.tsx +2 -2
- package/admin/src/components/TermTree.tsx +5 -5
- package/admin/src/components/VersionCompare.tsx +1 -1
- package/admin/src/components/VersionHistory.tsx +2 -2
- package/admin/src/components/fields/CategoryField.tsx +1 -1
- package/admin/src/components/fields/MediaField.tsx +4 -4
- package/admin/src/components/fields/ReferenceField.tsx +4 -4
- package/admin/src/components/fields/TagField.tsx +3 -3
- package/admin/src/components/filters/TaxonomyFilter.tsx +2 -2
- package/admin/src/components/media/MediaAssetEditDialog.tsx +2 -2
- package/admin/src/components/media/MediaFolderEditDialog.tsx +1 -1
- package/admin/src/components/media/MediaMoveModal.tsx +2 -2
- package/admin/src/components/media/MediaTaxonomyPicker.tsx +4 -4
- package/admin/src/components/ui/collapsible.tsx +7 -0
- package/admin/src/contexts/SettingsConfigContext.tsx +2 -2
- package/admin/src/embed/components/EmbedSidebar.tsx +163 -68
- package/admin/src/pages/MediaPage.tsx +1102 -8
- package/admin/src/pages/SettingsPage.tsx +171 -108
- package/admin/src/routes/entries/$entryId.tsx +2 -2
- package/admin/src/routes/entries/new.$contentTypeId.tsx +1 -1
- package/admin/src/routes/entries/type/$contentTypeId.tsx +6 -6
- package/admin/src/routes/media.tsx +23 -1094
- package/admin-dist/nitro.json +1 -1
- package/admin-dist/public/assets/{CmsEmptyState-CkqBIab3.js → CmsEmptyState-Do_erIgn.js} +1 -1
- package/admin-dist/public/assets/{CmsPageHeader-CUtl5MMG.js → CmsPageHeader-qDwPGi48.js} +1 -1
- package/admin-dist/public/assets/{CmsStatusBadge-CUYFgEe-.js → CmsStatusBadge-Dd9uToHE.js} +1 -1
- package/admin-dist/public/assets/{CmsSurface-CsJfAVa3.js → CmsSurface-DBy5Lumx.js} +1 -1
- package/admin-dist/public/assets/{CmsToolbar-CnfbcxeP.js → CmsToolbar-D1-Y-7SK.js} +1 -1
- package/admin-dist/public/assets/ContentEntryEditor-CWBiIx52.js +4 -0
- package/admin-dist/public/assets/{TaxonomyFilter-CWCxC5HZ.js → TaxonomyFilter-CdYQawxb.js} +1 -1
- package/admin-dist/public/assets/_contentTypeId-D9VMP6Gs.js +1 -0
- package/admin-dist/public/assets/_entryId-2FlCfqE7.js +1 -0
- package/admin-dist/public/assets/{alert-CF1BSzGR.js → alert-GxZx0y5c.js} +1 -1
- package/admin-dist/public/assets/{badge-CmuOIVKp.js → badge-BAlGIjop.js} +1 -1
- package/admin-dist/public/assets/{circle-check-big-BKDVG6DU.js → circle-check-big-CpLxAvEj.js} +1 -1
- package/admin-dist/public/assets/{command-XJxnF2Sd.js → command-di7XCqcv.js} +1 -1
- package/admin-dist/public/assets/content-D8zELsDG.js +1 -0
- package/admin-dist/public/assets/{content-types-CrNEm8Hf.js → content-types-BmzD0krT.js} +2 -2
- package/admin-dist/public/assets/globals-BvFfH-v9.css +1 -0
- package/admin-dist/public/assets/{index-C7xOwudI.js → index-zqfj4T_v.js} +1 -1
- package/admin-dist/public/assets/{label-CHCnXeBk.js → label-B6PPtKR5.js} +1 -1
- package/admin-dist/public/assets/{link-2-Bb34judH.js → link-2-W2fVnVOf.js} +1 -1
- package/admin-dist/public/assets/{list-9Pzt48ld.js → list-F8O0lZXC.js} +1 -1
- package/admin-dist/public/assets/main-dZT72bAG.js +97 -0
- package/admin-dist/public/assets/media-CETueFbV.js +1 -0
- package/admin-dist/public/assets/new._contentTypeId-BV2-TyyR.js +1 -0
- package/admin-dist/public/assets/{plus-Ceef7DHk.js → plus-AABQIF0N.js} +1 -1
- package/admin-dist/public/assets/{rotate-ccw-7k7-4VUq.js → rotate-ccw-BZpZtw0N.js} +1 -1
- package/admin-dist/public/assets/{scroll-area-CC6wujnp.js → scroll-area-CDfk-zrz.js} +1 -1
- package/admin-dist/public/assets/{search-DwoUV2pv.js → search-BvgYr-c9.js} +1 -1
- package/admin-dist/public/assets/{select-hOZTp8aC.js → select-BuiHcMzS.js} +1 -1
- package/admin-dist/public/assets/settings-DBxbYDvn.js +1 -0
- package/admin-dist/public/assets/{switch-jX2pDaNU.js → switch-DiJvolcs.js} +1 -1
- package/admin-dist/public/assets/tabs-Cgz6G_Xy.js +1 -0
- package/admin-dist/public/assets/{tanstack-adapter-B-Glm4kH.js → tanstack-adapter-BknsSgra.js} +1 -1
- package/admin-dist/public/assets/taxonomies-DOErsLl5.js +1 -0
- package/admin-dist/public/assets/{textarea-B6SfBmr0.js → textarea-CgggMxUX.js} +1 -1
- package/admin-dist/public/assets/{trash-BOCnIznD.js → trash-BU4ANuaW.js} +1 -1
- package/admin-dist/public/assets/{triangle-alert-CXFIO_Gu.js → triangle-alert-lvCbwp0s.js} +1 -1
- package/admin-dist/public/assets/{useBreadcrumbLabel-_6qBagc3.js → useBreadcrumbLabel-D00rvqjw.js} +1 -1
- package/admin-dist/public/assets/{usePermissions-M1ijZ7a6.js → usePermissions-D7tQowaF.js} +1 -1
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-collapsible.mjs +144 -0
- package/admin-dist/server/_chunks/_libs/@radix-ui/react-slot.mjs +21 -21
- package/admin-dist/server/_libs/lucide-react.mjs +131 -124
- package/admin-dist/server/_ssr/{CmsButton-DOiTVKQq.mjs → CmsButton-DbzfJru_.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsEmptyState-fbnGt3LD.mjs → CmsEmptyState-CuvcXr3Z.mjs} +3 -3
- package/admin-dist/server/_ssr/{CmsPageHeader-DHRrdOZa.mjs → CmsPageHeader-ClNPU7Up.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsStatusBadge-s7obWbKZ.mjs → CmsStatusBadge-CojMbrY7.mjs} +2 -2
- package/admin-dist/server/_ssr/{CmsSurface-rFoYjb62.mjs → CmsSurface-Dcv440rp.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsToolbar-zTE45z2q.mjs → CmsToolbar-BKv1nL6u.mjs} +2 -2
- package/admin-dist/server/_ssr/{ContentEntryEditor-BLoEjT_m.mjs → ContentEntryEditor-weiXSBdZ.mjs} +35 -51
- package/admin-dist/server/_ssr/{TaxonomyFilter-XAtaJC2z.mjs → TaxonomyFilter-BPQ57Mwk.mjs} +7 -7
- package/admin-dist/server/_ssr/{_contentTypeId-Csl4822C.mjs → _contentTypeId-DyyauLOs.mjs} +24 -23
- package/admin-dist/server/_ssr/{_entryId-D8alLFBx.mjs → _entryId-9Cafwxmw.mjs} +22 -21
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-Dk-FIYPN.mjs +4 -0
- package/admin-dist/server/_ssr/{command-C0Di14--.mjs → command-CEf8YBxY.mjs} +1 -1
- package/admin-dist/server/_ssr/{content-CT-FPsmV.mjs → content-ZFWVzO25.mjs} +20 -19
- package/admin-dist/server/_ssr/{content-types-C8cBFdzE.mjs → content-types-D25lUE-j.mjs} +18 -17
- package/admin-dist/server/_ssr/{index-BJtcrEc-.mjs → index-BlSIlH4Z.mjs} +10 -9
- package/admin-dist/server/_ssr/index.mjs +2 -2
- package/admin-dist/server/_ssr/{label-qn2Afwl4.mjs → label-PblVvdRv.mjs} +1 -1
- package/admin-dist/server/_ssr/{media-qv5IAsMZ.mjs → media-CD2_NUMw.mjs} +683 -314
- package/admin-dist/server/_ssr/{new._contentTypeId-DdGyrhqs.mjs → new._contentTypeId-dmZy6PBX.mjs} +20 -19
- package/admin-dist/server/_ssr/{router-nSVkxb6Y.mjs → router-x6Ab8T4s.mjs} +109 -43
- package/admin-dist/server/_ssr/{scroll-area-BCinP455.mjs → scroll-area-BH_1K-WT.mjs} +1 -1
- package/admin-dist/server/_ssr/{select-BKQlQScw.mjs → select-CrfEkFJw.mjs} +2 -2
- package/admin-dist/server/_ssr/{settings-BCr2KQlk.mjs → settings-DVdsoWoh.mjs} +158 -105
- package/admin-dist/server/_ssr/{switch-BaOi42fE.mjs → switch-DX_X8vZl.mjs} +1 -1
- package/admin-dist/server/_ssr/{tabs-DYXEi9kq.mjs → tabs-4FWM0sn8.mjs} +3 -3
- package/admin-dist/server/_ssr/{tanstack-adapter-Bsz8kha-.mjs → tanstack-adapter-D3ZcKtbY.mjs} +1 -1
- package/admin-dist/server/_ssr/{taxonomies-CueMHTbE.mjs → taxonomies-BHFfO9Yr.mjs} +21 -20
- package/admin-dist/server/_ssr/{textarea-CI0Jqx2x.mjs → textarea-CZVaroMc.mjs} +1 -1
- package/admin-dist/server/_ssr/{trash-DE6W8GoX.mjs → trash-9tUB2KwI.mjs} +14 -13
- package/admin-dist/server/_ssr/{useBreadcrumbLabel-B5Yi72lM.mjs → useBreadcrumbLabel-DVme3DSb.mjs} +1 -1
- package/admin-dist/server/_ssr/{usePermissions-C3nZ-Izm.mjs → usePermissions-zAQj-ruE.mjs} +1 -1
- package/admin-dist/server/index.mjs +188 -188
- package/dist/cli/commands/init.d.ts +12 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +136 -138
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/index.js +2 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/templates/admin.d.ts +10 -0
- package/dist/cli/templates/admin.d.ts.map +1 -0
- package/dist/cli/templates/admin.js +212 -0
- package/dist/cli/templates/admin.js.map +1 -0
- package/dist/cli/templates/cmsClient.d.ts +7 -0
- package/dist/cli/templates/cmsClient.d.ts.map +1 -0
- package/dist/cli/templates/cmsClient.js +36 -0
- package/dist/cli/templates/cmsClient.js.map +1 -0
- package/dist/cli/templates/cmsConfig.d.ts +7 -0
- package/dist/cli/templates/cmsConfig.d.ts.map +1 -0
- package/dist/cli/templates/cmsConfig.js +86 -0
- package/dist/cli/templates/cmsConfig.js.map +1 -0
- package/dist/cli/templates/index.d.ts +10 -0
- package/dist/cli/templates/index.d.ts.map +1 -0
- package/dist/cli/templates/index.js +10 -0
- package/dist/cli/templates/index.js.map +1 -0
- package/dist/cli/templates/schemas/blog.d.ts +8 -0
- package/dist/cli/templates/schemas/blog.d.ts.map +1 -0
- package/dist/cli/templates/schemas/blog.js +103 -0
- package/dist/cli/templates/schemas/blog.js.map +1 -0
- package/dist/cli/templates/schemas/docs.d.ts +8 -0
- package/dist/cli/templates/schemas/docs.d.ts.map +1 -0
- package/dist/cli/templates/schemas/docs.js +110 -0
- package/dist/cli/templates/schemas/docs.js.map +1 -0
- package/dist/cli/templates/schemas/index.d.ts +11 -0
- package/dist/cli/templates/schemas/index.d.ts.map +1 -0
- package/dist/cli/templates/schemas/index.js +13 -0
- package/dist/cli/templates/schemas/index.js.map +1 -0
- package/dist/cli/templates/schemas/landing.d.ts +8 -0
- package/dist/cli/templates/schemas/landing.d.ts.map +1 -0
- package/dist/cli/templates/schemas/landing.js +135 -0
- package/dist/cli/templates/schemas/landing.js.map +1 -0
- package/dist/cli/utils/fileUtils.d.ts +21 -0
- package/dist/cli/utils/fileUtils.d.ts.map +1 -0
- package/dist/cli/utils/fileUtils.js +95 -0
- package/dist/cli/utils/fileUtils.js.map +1 -0
- package/dist/cli/utils/prompts.d.ts +25 -0
- package/dist/cli/utils/prompts.d.ts.map +1 -0
- package/dist/cli/utils/prompts.js +87 -0
- package/dist/cli/utils/prompts.js.map +1 -0
- package/dist/client/admin/index.d.ts +75 -2
- package/dist/client/admin/index.d.ts.map +1 -1
- package/dist/client/admin/index.js +17 -1
- package/dist/client/admin/index.js.map +1 -1
- package/dist/client/admin/media.d.ts.map +1 -1
- package/dist/client/admin/media.js +3 -3
- package/dist/client/admin/media.js.map +1 -1
- package/dist/client/admin/settings.d.ts +50 -0
- package/dist/client/admin/settings.d.ts.map +1 -0
- package/dist/client/admin/settings.js +89 -0
- package/dist/client/admin/settings.js.map +1 -0
- package/dist/client/admin/taxonomies.d.ts.map +1 -1
- package/dist/client/admin/trash.d.ts.map +1 -1
- package/dist/client/admin/types.d.ts +40 -0
- package/dist/client/admin/types.d.ts.map +1 -1
- package/dist/client/admin/validators.d.ts +243 -3
- package/dist/client/admin/validators.d.ts.map +1 -1
- package/dist/client/admin/validators.js +18 -0
- package/dist/client/admin/validators.js.map +1 -1
- package/dist/client/adminConfig.d.ts +1 -1
- package/dist/client/agentTools.d.ts +1 -1427
- package/dist/client/agentTools.d.ts.map +1 -1
- package/dist/client/config.d.ts +145 -0
- package/dist/client/config.d.ts.map +1 -0
- package/dist/client/config.js +132 -0
- package/dist/client/config.js.map +1 -0
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +13 -6
- package/dist/client/index.js.map +1 -1
- package/dist/client/schema/defineContentType.js +1 -1
- package/dist/client/schema/defineContentType.js.map +1 -1
- package/dist/client/wrapper.d.ts.map +1 -1
- package/dist/client/wrapper.js +0 -4
- package/dist/client/wrapper.js.map +1 -1
- package/dist/component/_generated/api.d.ts +2 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +42 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/contentEntries.d.ts.map +1 -1
- package/dist/component/contentEntries.js +0 -2
- package/dist/component/contentEntries.js.map +1 -1
- package/dist/component/contentEntryMutations.d.ts.map +1 -1
- package/dist/component/contentEntryMutations.js +0 -1
- package/dist/component/contentEntryMutations.js.map +1 -1
- package/dist/component/contentLock.d.ts.map +1 -1
- package/dist/component/contentLock.js +0 -2
- package/dist/component/contentLock.js.map +1 -1
- package/dist/component/contentTypeMutations.d.ts +1 -1
- package/dist/component/index.d.ts +2 -1
- package/dist/component/index.d.ts.map +1 -1
- package/dist/component/index.js +3 -1
- package/dist/component/index.js.map +1 -1
- package/dist/component/schema.d.ts +18 -1
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +6 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/settings.d.ts +60 -0
- package/dist/component/settings.d.ts.map +1 -0
- package/dist/component/settings.js +126 -0
- package/dist/component/settings.js.map +1 -0
- package/dist/component/validators.d.ts +36 -0
- package/dist/component/validators.d.ts.map +1 -1
- package/dist/component/validators.js +15 -0
- package/dist/component/validators.js.map +1 -1
- package/dist/test.d.ts +16 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +2 -6
- package/dist/test.js.map +1 -1
- package/package.json +31 -22
- package/admin/README.md +0 -99
- package/admin-dist/public/assets/ContentEntryEditor-BU220CCy.js +0 -4
- package/admin-dist/public/assets/_contentTypeId-DK8cskRt.js +0 -1
- package/admin-dist/public/assets/_entryId-CuVMExbb.js +0 -1
- package/admin-dist/public/assets/content-QBUxdxbS.js +0 -1
- package/admin-dist/public/assets/globals-B7Wsfh_v.css +0 -1
- package/admin-dist/public/assets/main-CjQ2VI9L.js +0 -97
- package/admin-dist/public/assets/media-Dc5PWt2Q.js +0 -1
- package/admin-dist/public/assets/new._contentTypeId-C_I4YxIa.js +0 -1
- package/admin-dist/public/assets/settings-t2PbCZh4.js +0 -1
- package/admin-dist/public/assets/tabs-q4EbZk7c.js +0 -1
- package/admin-dist/public/assets/taxonomies-kyk5P4ZW.js +0 -1
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-BffZedId.mjs +0 -4
package/README.md
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
# Convex CMS
|
|
2
2
|
|
|
3
|
+
> **Alpha Status (v0.0.5)** — Actively developed. APIs may change. [Report issues](https://github.com/obkaro/convex-cms/issues).
|
|
4
|
+
|
|
3
5
|
A headless CMS built as a [Convex Component](https://docs.convex.dev/components) — content management that runs inside your Convex app.
|
|
4
6
|
|
|
7
|
+
## Why Convex CMS?
|
|
8
|
+
|
|
9
|
+
If you're building on Convex and need content management, this is the most integrated option:
|
|
10
|
+
|
|
11
|
+
- **Zero infrastructure** — Runs entirely within your Convex deployment
|
|
12
|
+
- **True real-time** — Content updates via Convex subscriptions, not polling
|
|
13
|
+
- **Type-safe** — Code-first schemas with full TypeScript inference
|
|
14
|
+
- **Component isolation** — Separate database tables, versioned independently
|
|
15
|
+
- **Agent-native** — 23 pre-built tools for AI agent integration via `@convex-dev/agent`
|
|
16
|
+
|
|
5
17
|
## Choose Your Path
|
|
6
18
|
|
|
7
19
|
### Need an Admin Interface?
|
|
@@ -17,7 +29,7 @@ Your App Admin UI
|
|
|
17
29
|
├── listContentTypes
|
|
18
30
|
├── getEntry
|
|
19
31
|
├── publishEntry
|
|
20
|
-
└── ... (
|
|
32
|
+
└── ... (60+ functions across 11 domains)
|
|
21
33
|
│
|
|
22
34
|
▼
|
|
23
35
|
CMS Component
|
|
@@ -75,7 +87,7 @@ They work together through the same CMS component.
|
|
|
75
87
|
### 1. Install
|
|
76
88
|
|
|
77
89
|
```bash
|
|
78
|
-
|
|
90
|
+
pnpm add convex-cms
|
|
79
91
|
```
|
|
80
92
|
|
|
81
93
|
### 2. Add the Component
|
|
@@ -92,7 +104,7 @@ export default app;
|
|
|
92
104
|
|
|
93
105
|
### 3. Choose Your Setup
|
|
94
106
|
|
|
95
|
-
**For Admin UI:** Run `
|
|
107
|
+
**For Admin UI:** Run `pnpm convex-cms init` then `pnpm convex-cms admin`
|
|
96
108
|
→ [Full Admin UI Setup](./docs/guides/admin-ui-setup.md)
|
|
97
109
|
|
|
98
110
|
**For Custom Functions:** Create a CMS client and use it in your functions
|
|
@@ -100,19 +112,39 @@ export default app;
|
|
|
100
112
|
|
|
101
113
|
## What's Included
|
|
102
114
|
|
|
103
|
-
|
|
115
|
+
### Core Content
|
|
116
|
+
- **13 field types** — text, richText, number, boolean, date, datetime, select, multiSelect, reference, media, json, tags, category
|
|
104
117
|
- **Publishing workflows** — draft → scheduled → published with version history
|
|
105
|
-
- **
|
|
118
|
+
- **Content versioning** — Snapshots, comparison, and rollback
|
|
119
|
+
- **Scheduled publishing** — Convex scheduler integration for future publish dates
|
|
120
|
+
|
|
121
|
+
### Media Management
|
|
122
|
+
- **File uploads** — Direct to Convex storage with folder organization
|
|
123
|
+
- **Image variants** — Automatic resizing and format conversion
|
|
124
|
+
- **Metadata & tagging** — Alt text, descriptions, taxonomy support
|
|
125
|
+
|
|
126
|
+
### Organization
|
|
127
|
+
- **Taxonomies** — Hierarchical categories and flat tags
|
|
128
|
+
- **Content locking** — Prevent concurrent edit conflicts
|
|
129
|
+
- **Soft delete & trash** — Configurable retention with restore
|
|
130
|
+
|
|
131
|
+
### Integration
|
|
106
132
|
- **RBAC** — 4 built-in roles + custom roles with fine-grained permissions
|
|
107
|
-
- **Multi-locale** —
|
|
108
|
-
- **
|
|
109
|
-
- **
|
|
133
|
+
- **Multi-locale** — Content localization with fallback chains
|
|
134
|
+
- **Webhooks** — Event-driven integration with external systems
|
|
135
|
+
- **Event system** — All mutations emit events for async processing
|
|
136
|
+
- **Agent tools** — 23 pre-built tools with Zod schemas for AI integration
|
|
137
|
+
- **Query builder** — Fluent API for complex content queries
|
|
138
|
+
|
|
139
|
+
### Admin UI
|
|
140
|
+
- **Pre-built React interface** — CLI mode for development, embeddable for production
|
|
141
|
+
- **Visual content editing** — Rich text, media picker, reference selector
|
|
110
142
|
|
|
111
143
|
## Admin UI Modes
|
|
112
144
|
|
|
113
145
|
| Mode | Command | Best For |
|
|
114
146
|
|------|---------|----------|
|
|
115
|
-
| **CLI** | `
|
|
147
|
+
| **CLI** | `pnpm convex-cms admin` | Development |
|
|
116
148
|
| **Embed** | `<CmsAdmin api={api.admin} />` | Production |
|
|
117
149
|
|
|
118
150
|
Both modes call the same functions from your `convex/admin.ts`.
|
|
@@ -121,17 +153,20 @@ Both modes call the same functions from your `convex/admin.ts`.
|
|
|
121
153
|
|
|
122
154
|
| Guide | Description |
|
|
123
155
|
|-------|-------------|
|
|
124
|
-
| [Admin UI Setup](./docs/guides/admin-ui-setup.md) | CLI and embed modes, auth integration |
|
|
125
156
|
| [Getting Started](./docs/guides/getting-started.md) | Programmatic usage with createCmsClient |
|
|
126
|
-
| [
|
|
157
|
+
| [Admin UI Setup](./docs/guides/admin-ui-setup.md) | CLI and embed modes, auth integration |
|
|
127
158
|
| [Content Modeling](./docs/guides/content-modeling.md) | Content types and field definitions |
|
|
159
|
+
| [Query Builder](./docs/guides/query-builder.md) | Fluent API for complex queries |
|
|
160
|
+
| [Taxonomies](./docs/guides/taxonomies.md) | Categories, tags, and organization |
|
|
128
161
|
| [Authorization](./docs/guides/authorization.md) | Roles, permissions, and custom auth |
|
|
129
162
|
| [Media Management](./docs/guides/media.md) | Uploads, folders, and variants |
|
|
163
|
+
| [Agent Tools](./docs/guides/agent-tools.md) | AI agent integration with Zod schemas |
|
|
164
|
+
| [Integration Patterns](./docs/guides/integration-patterns.md) | Common setups and when to use each |
|
|
130
165
|
|
|
131
166
|
| Reference | Description |
|
|
132
167
|
|-----------|-------------|
|
|
133
168
|
| [Client API](./docs/api/client-api.md) | createCmsClient methods |
|
|
134
|
-
| [Admin API](./docs/api/admin-api.md) | defineAdminAPI functions |
|
|
169
|
+
| [Admin API](./docs/api/admin-api.md) | 60+ defineAdminAPI functions |
|
|
135
170
|
| [Code-First Schema](./docs/api/code-first-schema.md) | TypeScript-first content types |
|
|
136
171
|
| [Field Types](./docs/api/field-types.md) | All 13 field types |
|
|
137
172
|
| [Configuration](./docs/api/configuration.md) | All config options |
|
|
@@ -27,10 +27,10 @@ export function BulkActionBar({
|
|
|
27
27
|
errors?: string[]
|
|
28
28
|
} | null>(null)
|
|
29
29
|
|
|
30
|
-
const bulkPublish = useMutation(api.
|
|
31
|
-
const bulkUnpublish = useMutation(api.
|
|
32
|
-
const bulkDelete = useMutation(api.
|
|
33
|
-
const bulkUpdate = useMutation(api.
|
|
30
|
+
const bulkPublish = useMutation(api.admin.bulkPublish)
|
|
31
|
+
const bulkUnpublish = useMutation(api.admin.bulkUnpublish)
|
|
32
|
+
const bulkDelete = useMutation(api.admin.bulkDelete)
|
|
33
|
+
const bulkUpdate = useMutation(api.admin.bulkUpdate)
|
|
34
34
|
|
|
35
35
|
const handleAction = useCallback((action: BulkAction) => {
|
|
36
36
|
setActiveAction(action)
|
|
@@ -188,14 +188,14 @@ export function ContentEntryEditor({
|
|
|
188
188
|
const formDataRef = useRef(formData)
|
|
189
189
|
formDataRef.current = formData
|
|
190
190
|
|
|
191
|
-
const createEntry = useMutation(api.
|
|
192
|
-
const updateEntry = useMutation(api.
|
|
193
|
-
const publishEntry = useMutation(api.
|
|
194
|
-
const unpublishEntry = useMutation(api.
|
|
195
|
-
const scheduleEntry = useMutation(api.
|
|
196
|
-
const cancelScheduleEntry = useMutation(api.
|
|
197
|
-
const deleteEntryMutation = useMutation(api.
|
|
198
|
-
const duplicateEntryMutation = useMutation(api.
|
|
191
|
+
const createEntry = useMutation(api.admin.createEntry)
|
|
192
|
+
const updateEntry = useMutation(api.admin.updateEntry)
|
|
193
|
+
const publishEntry = useMutation(api.admin.publishEntry)
|
|
194
|
+
const unpublishEntry = useMutation(api.admin.unpublishEntry)
|
|
195
|
+
const scheduleEntry = useMutation(api.admin.scheduleEntry)
|
|
196
|
+
const cancelScheduleEntry = useMutation(api.admin.cancelScheduledEntry)
|
|
197
|
+
const deleteEntryMutation = useMutation(api.admin.deleteEntry)
|
|
198
|
+
const duplicateEntryMutation = useMutation(api.admin.duplicateEntry)
|
|
199
199
|
|
|
200
200
|
const [showScheduleModal, setShowScheduleModal] = useState(false)
|
|
201
201
|
const [scheduleDateTime, setScheduleDateTime] = useState<string>(() => {
|
|
@@ -500,26 +500,6 @@ export function ContentEntryEditor({
|
|
|
500
500
|
}
|
|
501
501
|
}, [entry, publishEntry, onSave])
|
|
502
502
|
|
|
503
|
-
const _handleUnpublish = useCallback(async () => {
|
|
504
|
-
if (!entry) return
|
|
505
|
-
|
|
506
|
-
setIsPublishing(true)
|
|
507
|
-
setPublishError(null)
|
|
508
|
-
|
|
509
|
-
try {
|
|
510
|
-
const draftEntry = (await unpublishEntry({
|
|
511
|
-
id: entry._id,
|
|
512
|
-
})) as ContentEntry
|
|
513
|
-
onSave?.(draftEntry)
|
|
514
|
-
} catch (error) {
|
|
515
|
-
const message =
|
|
516
|
-
error instanceof Error ? error.message : 'Failed to unpublish'
|
|
517
|
-
setPublishError(message)
|
|
518
|
-
} finally {
|
|
519
|
-
setIsPublishing(false)
|
|
520
|
-
}
|
|
521
|
-
}, [entry, unpublishEntry, onSave])
|
|
522
|
-
|
|
523
503
|
const handleSchedule = useCallback(async () => {
|
|
524
504
|
if (!entry) return
|
|
525
505
|
|
|
@@ -188,8 +188,8 @@ export function ContentTypeFormModal({
|
|
|
188
188
|
const [showBreakingWarning, setShowBreakingWarning] = useState(false);
|
|
189
189
|
const [isForceUpdating, setIsForceUpdating] = useState(false);
|
|
190
190
|
|
|
191
|
-
const createContentType = useMutation(api.
|
|
192
|
-
const updateContentType = useMutation(api.
|
|
191
|
+
const createContentType = useMutation(api.admin.createContentType);
|
|
192
|
+
const updateContentType = useMutation(api.admin.updateContentType);
|
|
193
193
|
|
|
194
194
|
// Populate form when editing
|
|
195
195
|
useEffect(() => {
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import { Link, useRouterState } from "@tanstack/react-router";
|
|
2
|
-
import {
|
|
3
|
+
import { useQuery } from "convex/react";
|
|
4
|
+
import { Layers, ChevronDown } from "lucide-react";
|
|
3
5
|
import { cn } from "~/lib/cn";
|
|
4
6
|
import { useAdminConfig } from "~/contexts";
|
|
5
7
|
import { Icon } from "~/lib/icons";
|
|
8
|
+
import { api } from "../../convex/_generated/api";
|
|
9
|
+
import {
|
|
10
|
+
Collapsible,
|
|
11
|
+
CollapsibleTrigger,
|
|
12
|
+
CollapsibleContent,
|
|
13
|
+
} from "~/components/ui/collapsible";
|
|
14
|
+
import { ContentTypeFormModal } from "~/components/ContentTypeFormModal";
|
|
6
15
|
import type { NavItem } from "~/lib/admin-config";
|
|
7
16
|
|
|
8
17
|
export function Sidebar() {
|
|
@@ -11,6 +20,13 @@ export function Sidebar() {
|
|
|
11
20
|
const config = useAdminConfig();
|
|
12
21
|
const { navItems, branding, layout } = config;
|
|
13
22
|
|
|
23
|
+
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
|
24
|
+
|
|
25
|
+
const contentTypesResult = useQuery(api.admin.listContentTypes, {
|
|
26
|
+
isActive: true,
|
|
27
|
+
});
|
|
28
|
+
const contentTypes = contentTypesResult?.page ?? [];
|
|
29
|
+
|
|
14
30
|
const isActive = (to: string, exact?: boolean) => {
|
|
15
31
|
if (exact) {
|
|
16
32
|
return currentPath === to;
|
|
@@ -18,73 +34,149 @@ export function Sidebar() {
|
|
|
18
34
|
return currentPath.startsWith(to);
|
|
19
35
|
};
|
|
20
36
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const isContentActive =
|
|
38
|
+
currentPath === "/content" ||
|
|
39
|
+
currentPath.startsWith("/entries/type/") ||
|
|
40
|
+
currentPath.startsWith("/entries/new/") ||
|
|
41
|
+
currentPath.startsWith("/entries/");
|
|
42
|
+
|
|
43
|
+
const renderNavItem = (item: NavItem) => {
|
|
44
|
+
if (item.id === "content") {
|
|
45
|
+
return renderContentMenu(item);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Link
|
|
50
|
+
key={item.id}
|
|
51
|
+
to={item.path}
|
|
52
|
+
className={cn(
|
|
53
|
+
"flex items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
|
|
54
|
+
isActive(item.path, item.exact)
|
|
55
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
56
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground"
|
|
57
|
+
)}
|
|
58
|
+
>
|
|
59
|
+
<Icon name={item.icon} className="size-5" />
|
|
60
|
+
<span className="flex-1">{item.label}</span>
|
|
61
|
+
{item.badge && (
|
|
62
|
+
<span className="rounded-full bg-sidebar-primary px-2 py-0.5 text-xs text-sidebar-primary-foreground">
|
|
63
|
+
{item.badge}
|
|
64
|
+
</span>
|
|
65
|
+
)}
|
|
66
|
+
</Link>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const renderContentMenu = (item: NavItem) => (
|
|
71
|
+
<Collapsible key={item.id} defaultOpen={isContentActive}>
|
|
72
|
+
<CollapsibleTrigger
|
|
73
|
+
className={cn(
|
|
74
|
+
"flex w-full items-center gap-3 rounded-md px-2 py-2 text-sm font-medium transition-colors",
|
|
75
|
+
isContentActive
|
|
76
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
77
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
|
|
78
|
+
"group"
|
|
79
|
+
)}
|
|
80
|
+
>
|
|
81
|
+
<Icon name={item.icon} className="size-5" />
|
|
82
|
+
<span className="flex-1 text-left">{item.label}</span>
|
|
83
|
+
<ChevronDown className="size-4 transition-transform duration-200 group-data-[state=open]:rotate-180" />
|
|
84
|
+
</CollapsibleTrigger>
|
|
85
|
+
<CollapsibleContent>
|
|
86
|
+
<div className="ml-5 mt-1 space-y-1 border-l border-sidebar-border pl-3">
|
|
87
|
+
<Link
|
|
88
|
+
to="/content"
|
|
89
|
+
className={cn(
|
|
90
|
+
"flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
|
|
91
|
+
currentPath === "/content"
|
|
92
|
+
? "bg-sidebar-accent/60 text-sidebar-accent-foreground"
|
|
93
|
+
: "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
94
|
+
)}
|
|
95
|
+
>
|
|
96
|
+
All Entries
|
|
97
|
+
</Link>
|
|
98
|
+
{contentTypes.map((type) => (
|
|
99
|
+
<Link
|
|
100
|
+
key={type._id}
|
|
101
|
+
to="/entries/type/$contentTypeId"
|
|
102
|
+
params={{ contentTypeId: type._id }}
|
|
103
|
+
className={cn(
|
|
104
|
+
"flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
|
|
105
|
+
currentPath === `/entries/type/${type._id}`
|
|
106
|
+
? "bg-sidebar-accent/60 text-sidebar-accent-foreground"
|
|
107
|
+
: "text-sidebar-foreground/80 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
{type.displayName}
|
|
111
|
+
</Link>
|
|
112
|
+
))}
|
|
113
|
+
{contentTypes.length === 0 && contentTypesResult !== undefined && (
|
|
114
|
+
<button
|
|
115
|
+
type="button"
|
|
116
|
+
onClick={() => setIsCreateModalOpen(true)}
|
|
117
|
+
className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-sidebar-foreground/60 hover:bg-sidebar-accent/30 hover:text-sidebar-accent-foreground"
|
|
118
|
+
>
|
|
119
|
+
+ Create content type
|
|
120
|
+
</button>
|
|
121
|
+
)}
|
|
122
|
+
</div>
|
|
123
|
+
</CollapsibleContent>
|
|
124
|
+
</Collapsible>
|
|
40
125
|
);
|
|
41
126
|
|
|
42
127
|
const sidebarWidth = layout.sidebarWidth;
|
|
43
128
|
|
|
44
129
|
return (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
130
|
+
<>
|
|
131
|
+
<aside
|
|
132
|
+
className="fixed inset-y-0 left-0 z-50 flex flex-col border-r border-sidebar-border bg-sidebar"
|
|
133
|
+
style={{ width: sidebarWidth }}
|
|
134
|
+
>
|
|
135
|
+
<div className="flex h-14 items-center gap-2 border-b border-sidebar-border px-4">
|
|
136
|
+
<Link to="/" className="flex items-center gap-2 font-semibold text-sidebar-foreground">
|
|
137
|
+
{branding.logo ? (
|
|
138
|
+
<img src={branding.logo} alt={branding.appName} className="size-8" />
|
|
139
|
+
) : (
|
|
140
|
+
<div className="flex size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
|
|
141
|
+
<Layers className="size-4" />
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
144
|
+
<span className="text-base">{branding.appName}</span>
|
|
145
|
+
</Link>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<nav className="flex-1 space-y-6 overflow-y-auto p-4">
|
|
149
|
+
{navItems.main.length > 0 && (
|
|
150
|
+
<div className="space-y-1">
|
|
151
|
+
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
152
|
+
Main
|
|
153
|
+
</span>
|
|
154
|
+
<div className="space-y-1 pt-2">{navItems.main.map(renderNavItem)}</div>
|
|
56
155
|
</div>
|
|
57
156
|
)}
|
|
58
|
-
<span className="text-base">{branding.appName}</span>
|
|
59
|
-
</Link>
|
|
60
|
-
</div>
|
|
61
157
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
158
|
+
{navItems.config.length > 0 && (
|
|
159
|
+
<div className="space-y-1">
|
|
160
|
+
<span className="px-2 text-xs font-medium uppercase tracking-wider text-sidebar-foreground/60">
|
|
161
|
+
Configuration
|
|
162
|
+
</span>
|
|
163
|
+
<div className="space-y-1 pt-2">{navItems.config.map(renderNavItem)}</div>
|
|
164
|
+
</div>
|
|
165
|
+
)}
|
|
166
|
+
</nav>
|
|
71
167
|
|
|
72
|
-
|
|
73
|
-
<div className="
|
|
74
|
-
<span
|
|
75
|
-
|
|
76
|
-
</span>
|
|
77
|
-
<div className="space-y-1 pt-2">{navItems.config.map(renderNavItem)}</div>
|
|
168
|
+
<div className="border-t border-sidebar-border p-4">
|
|
169
|
+
<div className="flex items-center justify-between text-xs text-sidebar-foreground/60">
|
|
170
|
+
<span>Version</span>
|
|
171
|
+
<span className="font-mono">0.1.0</span>
|
|
78
172
|
</div>
|
|
79
|
-
)}
|
|
80
|
-
</nav>
|
|
81
|
-
|
|
82
|
-
<div className="border-t border-sidebar-border p-4">
|
|
83
|
-
<div className="flex items-center justify-between text-xs text-sidebar-foreground/60">
|
|
84
|
-
<span>Version</span>
|
|
85
|
-
<span className="font-mono">0.1.0</span>
|
|
86
173
|
</div>
|
|
87
|
-
</
|
|
88
|
-
|
|
174
|
+
</aside>
|
|
175
|
+
|
|
176
|
+
<ContentTypeFormModal
|
|
177
|
+
isOpen={isCreateModalOpen}
|
|
178
|
+
onClose={() => setIsCreateModalOpen(false)}
|
|
179
|
+
/>
|
|
180
|
+
</>
|
|
89
181
|
);
|
|
90
182
|
}
|
|
@@ -49,8 +49,8 @@ export function TaxonomyEditor({
|
|
|
49
49
|
const [submitError, setSubmitError] = useState<string | null>(null)
|
|
50
50
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false)
|
|
51
51
|
|
|
52
|
-
const createTaxonomy = useMutation(api.
|
|
53
|
-
const updateTaxonomy = useMutation(api.
|
|
52
|
+
const createTaxonomy = useMutation(api.admin.createTaxonomy)
|
|
53
|
+
const updateTaxonomy = useMutation(api.admin.updateTaxonomy)
|
|
54
54
|
|
|
55
55
|
useEffect(() => {
|
|
56
56
|
if (taxonomy) {
|
|
@@ -42,10 +42,10 @@ export function TermTree({
|
|
|
42
42
|
const [error, setError] = useState<string | null>(null)
|
|
43
43
|
|
|
44
44
|
const termsQuery = isHierarchical
|
|
45
|
-
? useQuery(api.
|
|
46
|
-
: useQuery(api.
|
|
45
|
+
? useQuery(api.admin.getTermsHierarchy, { taxonomyId })
|
|
46
|
+
: useQuery(api.admin.listTerms, { taxonomyId })
|
|
47
47
|
|
|
48
|
-
const deleteTerm = useMutation(api.
|
|
48
|
+
const deleteTerm = useMutation(api.admin.deleteTerm)
|
|
49
49
|
|
|
50
50
|
const terms = (
|
|
51
51
|
isHierarchical ? termsQuery : (termsQuery as { page?: Term[] })?.page
|
|
@@ -304,8 +304,8 @@ function TermEditModal({
|
|
|
304
304
|
const [submitError, setSubmitError] = useState<string | null>(null)
|
|
305
305
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false)
|
|
306
306
|
|
|
307
|
-
const createTerm = useMutation(api.
|
|
308
|
-
const updateTerm = useMutation(api.
|
|
307
|
+
const createTerm = useMutation(api.admin.createTerm)
|
|
308
|
+
const updateTerm = useMutation(api.admin.updateTerm)
|
|
309
309
|
|
|
310
310
|
const handleChange = useCallback(
|
|
311
311
|
(field: keyof typeof formData, value: string | number) => {
|
|
@@ -47,7 +47,7 @@ export function VersionCompare({
|
|
|
47
47
|
onClose,
|
|
48
48
|
onRollback,
|
|
49
49
|
}: VersionCompareProps) {
|
|
50
|
-
const comparisonQuery = useQuery(api.
|
|
50
|
+
const comparisonQuery = useQuery(api.admin.compareVersions, {
|
|
51
51
|
entryId,
|
|
52
52
|
fromVersionNumber: fromVersion,
|
|
53
53
|
toVersionNumber: toVersion,
|
|
@@ -42,12 +42,12 @@ export function VersionHistory({
|
|
|
42
42
|
const [rollbackError, setRollbackError] = useState<string | null>(null)
|
|
43
43
|
const [rollbackSuccess, setRollbackSuccess] = useState(false)
|
|
44
44
|
|
|
45
|
-
const versionsQuery = useQuery(api.
|
|
45
|
+
const versionsQuery = useQuery(api.admin.getVersionHistory, {
|
|
46
46
|
entryId,
|
|
47
47
|
paginationOpts: { numItems: 50, cursor: null },
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
const rollbackMutation = useMutation(api.
|
|
50
|
+
const rollbackMutation = useMutation(api.admin.rollbackVersion)
|
|
51
51
|
|
|
52
52
|
const versions = (versionsQuery?.page ?? []) as VersionItem[]
|
|
53
53
|
const isLoading = versionsQuery === undefined
|
|
@@ -52,7 +52,7 @@ export function CategoryField({
|
|
|
52
52
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
53
53
|
|
|
54
54
|
const hierarchyResult = useQuery(
|
|
55
|
-
api.
|
|
55
|
+
api.admin.getTermsHierarchy,
|
|
56
56
|
taxonomyId ? { taxonomyId: asTaxonomyId(taxonomyId) } : 'skip'
|
|
57
57
|
)
|
|
58
58
|
const categoryTree = (hierarchyResult ?? []) as CategoryTerm[]
|
|
@@ -105,12 +105,12 @@ export function MediaField({
|
|
|
105
105
|
const allowedMimeTypes = field.options?.allowedMimeTypes ?? []
|
|
106
106
|
|
|
107
107
|
const selectedAsset = useQuery(
|
|
108
|
-
api.
|
|
108
|
+
api.admin.getMediaAsset,
|
|
109
109
|
value ? { id: value } : 'skip'
|
|
110
110
|
)
|
|
111
111
|
|
|
112
112
|
const assetsResult = useQuery(
|
|
113
|
-
api.
|
|
113
|
+
api.admin.listMediaAssets,
|
|
114
114
|
showPicker
|
|
115
115
|
? {
|
|
116
116
|
type: typeFilter
|
|
@@ -345,8 +345,8 @@ export function MediaField({
|
|
|
345
345
|
|
|
346
346
|
<TabsContent value="upload" className="mt-4">
|
|
347
347
|
<UploadDropzone
|
|
348
|
-
generateUploadUrl={api.
|
|
349
|
-
createAsset={api.
|
|
348
|
+
generateUploadUrl={api.admin.generateUploadUrl}
|
|
349
|
+
createAsset={api.admin.createMediaAsset}
|
|
350
350
|
onUploadComplete={handleUploadComplete}
|
|
351
351
|
allowedMimeTypes={allowedMimeTypes}
|
|
352
352
|
maxFileSize={field.options?.maxFileSize}
|
|
@@ -75,7 +75,7 @@ export function ReferenceField({
|
|
|
75
75
|
return Array.isArray(value) ? value : [value]
|
|
76
76
|
}, [value])
|
|
77
77
|
|
|
78
|
-
const contentTypes = useQuery(api.
|
|
78
|
+
const contentTypes = useQuery(api.admin.listContentTypes, {
|
|
79
79
|
isActive: true,
|
|
80
80
|
includeEntryCounts: false,
|
|
81
81
|
})
|
|
@@ -91,12 +91,12 @@ export function ReferenceField({
|
|
|
91
91
|
}, [contentTypes?.page, allowedContentTypes])
|
|
92
92
|
|
|
93
93
|
const selectedEntry = useQuery(
|
|
94
|
-
api.
|
|
94
|
+
api.admin.getEntry,
|
|
95
95
|
selectedIds.length === 1 ? { id: selectedIds[0] } : 'skip'
|
|
96
96
|
)
|
|
97
97
|
|
|
98
98
|
const selectedEntries = useQuery(
|
|
99
|
-
api.
|
|
99
|
+
api.admin.listEntries,
|
|
100
100
|
selectedIds.length > 1
|
|
101
101
|
? {
|
|
102
102
|
paginationOpts: { numItems: 100, cursor: null },
|
|
@@ -110,7 +110,7 @@ export function ReferenceField({
|
|
|
110
110
|
}, [selectedEntries?.page, selectedIds])
|
|
111
111
|
|
|
112
112
|
const entriesResult = useQuery(
|
|
113
|
-
api.
|
|
113
|
+
api.admin.listEntries,
|
|
114
114
|
showPicker
|
|
115
115
|
? {
|
|
116
116
|
contentTypeId: contentTypeFilter || undefined,
|
|
@@ -51,7 +51,7 @@ export function TagField({
|
|
|
51
51
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
52
52
|
|
|
53
53
|
const suggestionsResult = useQuery(
|
|
54
|
-
api.
|
|
54
|
+
api.admin.suggestTerms,
|
|
55
55
|
taxonomyId
|
|
56
56
|
? {
|
|
57
57
|
taxonomyId: asTaxonomyId(taxonomyId),
|
|
@@ -64,7 +64,7 @@ export function TagField({
|
|
|
64
64
|
const suggestions = suggestionsResult ?? []
|
|
65
65
|
|
|
66
66
|
const selectedTermsResult = useQuery(
|
|
67
|
-
api.
|
|
67
|
+
api.admin.listTerms,
|
|
68
68
|
taxonomyId && value && value.length > 0
|
|
69
69
|
? {
|
|
70
70
|
taxonomyId: asTaxonomyId(taxonomyId),
|
|
@@ -82,7 +82,7 @@ export function TagField({
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const createTermMutation = useMutation(api.
|
|
85
|
+
const createTermMutation = useMutation(api.admin.createTerm)
|
|
86
86
|
|
|
87
87
|
useEffect(() => {
|
|
88
88
|
function handleClickOutside(event: MouseEvent) {
|
|
@@ -49,7 +49,7 @@ export function TaxonomyFilter({
|
|
|
49
49
|
const [open, setOpen] = useState(false)
|
|
50
50
|
const [search, setSearch] = useState('')
|
|
51
51
|
|
|
52
|
-
const taxonomiesResult = useQuery(api.
|
|
52
|
+
const taxonomiesResult = useQuery(api.admin.listTaxonomies, { isActive: true })
|
|
53
53
|
const taxonomies = taxonomiesResult?.page ?? []
|
|
54
54
|
|
|
55
55
|
const activeTaxonomy = useMemo(() => {
|
|
@@ -62,7 +62,7 @@ export function TaxonomyFilter({
|
|
|
62
62
|
const targetTaxonomyId = taxonomyId ?? taxonomies[0]?._id
|
|
63
63
|
|
|
64
64
|
const termsResult = useQuery(
|
|
65
|
-
api.
|
|
65
|
+
api.admin.listTerms,
|
|
66
66
|
targetTaxonomyId
|
|
67
67
|
? {
|
|
68
68
|
taxonomyId: targetTaxonomyId,
|
|
@@ -38,9 +38,9 @@ export function MediaAssetEditDialog({
|
|
|
38
38
|
const [isSaving, setIsSaving] = useState(false)
|
|
39
39
|
const [error, setError] = useState('')
|
|
40
40
|
|
|
41
|
-
const updateAsset = useMutation(api.
|
|
41
|
+
const updateAsset = useMutation(api.admin.updateMediaAsset)
|
|
42
42
|
|
|
43
|
-
const taxonomiesResult = useQuery(api.
|
|
43
|
+
const taxonomiesResult = useQuery(api.admin.listTaxonomies, {
|
|
44
44
|
isActive: true,
|
|
45
45
|
paginationOpts: { numItems: 50, cursor: null },
|
|
46
46
|
})
|
|
@@ -31,7 +31,7 @@ export function MediaFolderEditDialog({
|
|
|
31
31
|
const [isSaving, setIsSaving] = useState(false)
|
|
32
32
|
const [error, setError] = useState('')
|
|
33
33
|
|
|
34
|
-
const updateFolder = useMutation(api.
|
|
34
|
+
const updateFolder = useMutation(api.admin.updateMediaFolder)
|
|
35
35
|
|
|
36
36
|
useEffect(() => {
|
|
37
37
|
if (folder) {
|
|
@@ -34,8 +34,8 @@ export function MediaMoveModal({
|
|
|
34
34
|
const [isMoving, setIsMoving] = useState(false)
|
|
35
35
|
const [error, setError] = useState('')
|
|
36
36
|
|
|
37
|
-
const folderTree = useQuery(api.
|
|
38
|
-
const moveAssets = useMutation(api.
|
|
37
|
+
const folderTree = useQuery(api.admin.getMediaFolderTree, {})
|
|
38
|
+
const moveAssets = useMutation(api.admin.moveMediaAssets)
|
|
39
39
|
|
|
40
40
|
const sortedFolders = useMemo(() => {
|
|
41
41
|
if (!folderTree) return []
|