convex-cms 0.0.8 → 0.0.9-alpha.1
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 +11 -1
- package/admin/src/components/BulkActionBar.tsx +6 -5
- package/admin/src/components/ContentEntryEditor.tsx +10 -9
- package/admin/src/components/ContentTypeFormModal.tsx +4 -3
- package/admin/src/components/Sidebar.tsx +3 -2
- package/admin/src/components/TaxonomyEditor.tsx +4 -3
- package/admin/src/components/TermTree.tsx +8 -6
- package/admin/src/components/VersionCompare.tsx +3 -2
- package/admin/src/components/VersionHistory.tsx +4 -3
- package/admin/src/components/fields/CategoryField.tsx +3 -2
- package/admin/src/components/fields/MediaField.tsx +6 -5
- package/admin/src/components/fields/ReferenceField.tsx +6 -5
- package/admin/src/components/fields/TagField.tsx +5 -4
- package/admin/src/components/filters/TaxonomyFilter.tsx +4 -3
- package/admin/src/components/media/MediaAssetEditDialog.tsx +4 -3
- package/admin/src/components/media/MediaFolderEditDialog.tsx +3 -2
- package/admin/src/components/media/MediaMoveModal.tsx +4 -3
- package/admin/src/components/media/MediaTaxonomyPicker.tsx +6 -5
- package/admin/src/contexts/SettingsConfigContext.tsx +19 -5
- package/admin/src/embed/contexts/ApiContext.tsx +6 -2
- package/admin/src/routes/__root.tsx +7 -3
- package/admin-dist/nitro.json +1 -1
- package/admin-dist/public/assets/{CmsEmptyState-6-PLaXtD.js → CmsEmptyState-BM4e6N83.js} +1 -1
- package/admin-dist/public/assets/{CmsPageHeader-SoF4Epu9.js → CmsPageHeader-uor3DPIk.js} +1 -1
- package/admin-dist/public/assets/{CmsStatusBadge-D7kYaohx.js → CmsStatusBadge-D8N18LJx.js} +1 -1
- package/admin-dist/public/assets/{CmsSurface-BvksBm6W.js → CmsSurface-BEcY-WpI.js} +1 -1
- package/admin-dist/public/assets/{CmsToolbar-DlZPMe2B.js → CmsToolbar-DE-bu3W8.js} +1 -1
- package/admin-dist/public/assets/ContentEntryEditor-BdkIMCUk.js +4 -0
- package/admin-dist/public/assets/TaxonomyFilter-a1-O9DPs.js +1 -0
- package/admin-dist/public/assets/{_contentTypeId-DTv8UoTp.js → _contentTypeId-XIkYOLyY.js} +1 -1
- package/admin-dist/public/assets/{_entryId-D3lr5Dvy.js → _entryId-DyP15QpI.js} +1 -1
- package/admin-dist/public/assets/{alert-BAHTL6ao.js → alert-DHBQuuib.js} +1 -1
- package/admin-dist/public/assets/{badge-oJv4Eai8.js → badge-BOhWFWzb.js} +1 -1
- package/admin-dist/public/assets/{circle-check-big-3OHxNDhO.js → circle-check-big-DjTNapen.js} +1 -1
- package/admin-dist/public/assets/{command-DwgQs69u.js → command-BIc5_8gL.js} +1 -1
- package/admin-dist/public/assets/content-C3N8Ugra.js +1 -0
- package/admin-dist/public/assets/content-types-D0wh1eUF.js +1 -0
- package/admin-dist/public/assets/{index-DOkgTSx0.js → index-B-g3F_ri.js} +1 -1
- package/admin-dist/public/assets/main-BapBJgQD.js +102 -0
- package/admin-dist/public/assets/media-8uh1MwDi.js +1 -0
- package/admin-dist/public/assets/{new._contentTypeId-VF63rpic.js → new._contentTypeId-S96rFbgY.js} +1 -1
- package/admin-dist/public/assets/{pencil-CX1CiTDD.js → pencil-DgaZav4e.js} +1 -1
- package/admin-dist/public/assets/{refresh-cw-Cm-YOeFI.js → refresh-cw-BBut4hAU.js} +1 -1
- package/admin-dist/public/assets/{rotate-ccw-B45JsL5f.js → rotate-ccw-DVCkojZZ.js} +1 -1
- package/admin-dist/public/assets/{scroll-area-b3A1HHR7.js → scroll-area-DPC4uXzf.js} +1 -1
- package/admin-dist/public/assets/{search-DKKh_DdH.js → search-CSyHHglh.js} +1 -1
- package/admin-dist/public/assets/{settings-CGVDEV1r.js → settings-cEqPsoJ0.js} +1 -1
- package/admin-dist/public/assets/{switch-BTMY8Qnk.js → switch-O2BviO8Q.js} +1 -1
- package/admin-dist/public/assets/{tabs-DUQwUoIb.js → tabs-p1MWhOqY.js} +1 -1
- package/admin-dist/public/assets/{tanstack-adapter-f7AHmQ5L.js → tanstack-adapter-CDrxoPZD.js} +1 -1
- package/admin-dist/public/assets/taxonomies-DJ9UbjXW.js +1 -0
- package/admin-dist/public/assets/{trash-D7e0uKd9.js → trash-RnpP6lXF.js} +1 -1
- package/admin-dist/public/assets/{useBreadcrumbLabel-CF2KYwsw.js → useBreadcrumbLabel-zbIWXlkc.js} +1 -1
- package/admin-dist/public/assets/{usePermissions-DWBImEOW.js → usePermissions-4CTlK-vU.js} +1 -1
- package/admin-dist/server/_chunks/_libs/@floating-ui/core.mjs +71 -65
- package/admin-dist/server/_chunks/_libs/@floating-ui/dom.mjs +1 -1
- package/admin-dist/server/_chunks/_libs/@floating-ui/utils.mjs +8 -8
- package/admin-dist/server/_chunks/_libs/@tanstack/react-router.mjs +12 -30
- package/admin-dist/server/_chunks/_libs/@tanstack/react-store.mjs +1 -56
- package/admin-dist/server/_chunks/_libs/@tanstack/router-core.mjs +130 -114
- package/admin-dist/server/_chunks/_libs/@tanstack/store.mjs +1 -134
- package/admin-dist/server/_chunks/_libs/react-dom.mjs +5 -5
- package/admin-dist/server/_chunks/_libs/react.mjs +1 -1
- package/admin-dist/server/_libs/isbot.mjs +1 -1
- package/admin-dist/server/_libs/use-sync-external-store.mjs +1 -76
- package/admin-dist/server/_ssr/{CmsEmptyState-BM8DghTl.mjs → CmsEmptyState-BA0Lc5xs.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsPageHeader-BHUmrIWD.mjs → CmsPageHeader-PMyecILZ.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsStatusBadge-D0Zb0oRl.mjs → CmsStatusBadge-CInuN2bZ.mjs} +2 -2
- package/admin-dist/server/_ssr/{CmsSurface-B2eBr-47.mjs → CmsSurface-CH1PIfcS.mjs} +1 -1
- package/admin-dist/server/_ssr/{CmsToolbar-BCrwg7OL.mjs → CmsToolbar-IuhSA7gR.mjs} +1 -1
- package/admin-dist/server/_ssr/{ContentEntryEditor-Cjfm0uhr.mjs → ContentEntryEditor-Bzhir4fQ.mjs} +38 -31
- package/admin-dist/server/_ssr/{TaxonomyFilter-C4pD0kfM.mjs → TaxonomyFilter-r4izSMBh.mjs} +6 -5
- package/admin-dist/server/_ssr/{_contentTypeId-CiDiX-p7.mjs → _contentTypeId-BWEbjqxY.mjs} +11 -13
- package/admin-dist/server/_ssr/{_entryId-9GxatOkL.mjs → _entryId-B5xoXoJf.mjs} +12 -14
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-CBTan6ii.mjs +4 -0
- package/admin-dist/server/_ssr/{badge-EI998zba.mjs → badge-DXrjBRqZ.mjs} +1 -1
- package/admin-dist/server/_ssr/{command-BLAWQhUw.mjs → command-Cj90OdCX.mjs} +1 -1
- package/admin-dist/server/_ssr/config.server-BOr7Jxr4.mjs +0 -3
- package/admin-dist/server/_ssr/{content-BHX39L4D.mjs → content-DKRI-YqL.mjs} +14 -15
- package/admin-dist/server/_ssr/{content-types-DCzrBhTH.mjs → content-types-BzgRcS8K.mjs} +7 -9
- package/admin-dist/server/_ssr/{index-DwM_5VNP.mjs → index-BPf6_agY.mjs} +4 -6
- package/admin-dist/server/_ssr/index.mjs +11 -10
- package/admin-dist/server/_ssr/{media-CbzgTRRQ.mjs → media-MpjxOZL8.mjs} +23 -21
- package/admin-dist/server/_ssr/{new._contentTypeId-6Ph-Gtlw.mjs → new._contentTypeId-DSb4qR9j.mjs} +11 -13
- package/admin-dist/server/_ssr/{router-vd1nySeP.mjs → router-Dk9ikPNc.mjs} +61 -47
- package/admin-dist/server/_ssr/{scroll-area--B9snFTJ.mjs → scroll-area-JwVD_6MZ.mjs} +1 -1
- package/admin-dist/server/_ssr/{settings-DlTO2JSj.mjs → settings-KVJNe0GM.mjs} +8 -10
- package/admin-dist/server/_ssr/{switch-C05NgNW0.mjs → switch-DvREvRv4.mjs} +1 -1
- package/admin-dist/server/_ssr/{tabs-DAk2J5xy.mjs → tabs-B0h57pFf.mjs} +1 -1
- package/admin-dist/server/_ssr/{tanstack-adapter-DWbaPByn.mjs → tanstack-adapter-gmM64LnW.mjs} +1 -1
- package/admin-dist/server/_ssr/{taxonomies-B8nqce6u.mjs → taxonomies-BbBNx260.mjs} +17 -16
- package/admin-dist/server/_ssr/{trash-zdlZgpTo.mjs → trash-JAzYGh7A.mjs} +8 -10
- package/admin-dist/server/_ssr/{useBreadcrumbLabel-DpEKyG1h.mjs → useBreadcrumbLabel-BWIujj97.mjs} +1 -1
- package/admin-dist/server/_ssr/{usePermissions-olYRd9S9.mjs → usePermissions-CcLDCSwa.mjs} +1 -1
- package/admin-dist/server/index.mjs +162 -162
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +18 -29
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/templates/admin.d.ts +4 -3
- package/dist/cli/templates/admin.d.ts.map +1 -1
- package/dist/cli/templates/admin.js +152 -195
- package/dist/cli/templates/admin.js.map +1 -1
- package/dist/cli/templates/cmsClient.d.ts +2 -2
- package/dist/cli/templates/cmsClient.d.ts.map +1 -1
- package/dist/cli/templates/cmsClient.js +58 -27
- package/dist/cli/templates/cmsClient.js.map +1 -1
- package/dist/cli/templates/content.d.ts +10 -0
- package/dist/cli/templates/content.d.ts.map +1 -0
- package/dist/cli/templates/content.js +257 -0
- package/dist/cli/templates/content.js.map +1 -0
- package/dist/cli/templates/index.d.ts +3 -2
- package/dist/cli/templates/index.d.ts.map +1 -1
- package/dist/cli/templates/index.js +3 -2
- package/dist/cli/templates/index.js.map +1 -1
- package/dist/cli/templates/schemas/blog.d.ts +4 -3
- package/dist/cli/templates/schemas/blog.d.ts.map +1 -1
- package/dist/cli/templates/schemas/blog.js +44 -13
- package/dist/cli/templates/schemas/blog.js.map +1 -1
- package/dist/cli/templates/schemas/docs.d.ts +4 -3
- package/dist/cli/templates/schemas/docs.d.ts.map +1 -1
- package/dist/cli/templates/schemas/docs.js +43 -12
- package/dist/cli/templates/schemas/docs.js.map +1 -1
- package/dist/cli/templates/schemas/index.d.ts +6 -4
- package/dist/cli/templates/schemas/index.d.ts.map +1 -1
- package/dist/cli/templates/schemas/index.js +6 -4
- package/dist/cli/templates/schemas/index.js.map +1 -1
- package/dist/cli/templates/schemas/landing.d.ts +4 -3
- package/dist/cli/templates/schemas/landing.d.ts.map +1 -1
- package/dist/cli/templates/schemas/landing.js +62 -15
- package/dist/cli/templates/schemas/landing.js.map +1 -1
- package/dist/cli/utils/fileUtils.d.ts.map +1 -1
- package/dist/cli/utils/fileUtils.js +6 -5
- package/dist/cli/utils/fileUtils.js.map +1 -1
- package/dist/client/admin/index.d.ts +2 -1
- package/dist/client/admin/index.d.ts.map +1 -1
- package/dist/client/admin/index.js.map +1 -1
- package/dist/client/admin/types.d.ts +14 -1
- package/dist/client/admin/types.d.ts.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/react/index.d.ts +176 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +162 -0
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/admin-dist/public/assets/ContentEntryEditor-C6n9xLS9.js +0 -4
- package/admin-dist/public/assets/TaxonomyFilter-CFX1_g8s.js +0 -1
- package/admin-dist/public/assets/content-CKQ4QwW2.js +0 -1
- package/admin-dist/public/assets/content-types-BrttaLpc.js +0 -1
- package/admin-dist/public/assets/main-DV6oxWnU.js +0 -102
- package/admin-dist/public/assets/media-B2i-mCbx.js +0 -1
- package/admin-dist/public/assets/taxonomies-DvMppdiD.js +0 -1
- package/admin-dist/server/_ssr/_tanstack-start-manifest_v-CC7UrHKE.mjs +0 -4
package/README.md
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/convex-cms)
|
|
4
4
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
5
|
|
|
6
|
-
> **Alpha (v0.0.
|
|
6
|
+
> **Alpha (v0.0.8)** Actively developed. APIs may change. [Report issues](https://github.com/obkaro/convex-cms/issues).
|
|
7
7
|
|
|
8
8
|
A headless CMS built as a [Convex Component](https://docs.convex.dev/components). Content management that runs inside your Convex app.
|
|
9
9
|
|
|
10
|
+
[](https://convex-cms-example.vercel.app)
|
|
11
|
+
|
|
12
|
+
[Live Demo](https://convex-cms-example.vercel.app)
|
|
13
|
+
|
|
10
14
|
## Quick Start
|
|
11
15
|
|
|
12
16
|
### 1. Install
|
|
@@ -146,3 +150,9 @@ Both modes call the same functions from your `convex/admin.ts`.
|
|
|
146
150
|
## License
|
|
147
151
|
|
|
148
152
|
Apache-2.0
|
|
153
|
+
|
|
154
|
+
## Support
|
|
155
|
+
|
|
156
|
+
- [GitHub Issues](https://github.com/obkaro/convex-cms/issues): Bug reports and feature requests
|
|
157
|
+
- [Discord Community](https://discord.gg/convex): Chat with other users
|
|
158
|
+
- [Convex Documentation](https://docs.convex.dev): Learn about Convex
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback } from 'react'
|
|
2
2
|
import { useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { BulkOperationModal } from './BulkOperationModal'
|
|
5
5
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
6
6
|
import { Badge } from '~/components/ui/badge'
|
|
@@ -19,6 +19,7 @@ export function BulkActionBar({
|
|
|
19
19
|
onClearSelection,
|
|
20
20
|
onOperationComplete,
|
|
21
21
|
}: BulkActionBarProps) {
|
|
22
|
+
const api = useApi()
|
|
22
23
|
const [activeAction, setActiveAction] = useState<BulkAction | null>(null)
|
|
23
24
|
const [isProcessing, setIsProcessing] = useState(false)
|
|
24
25
|
const [result, setResult] = useState<{
|
|
@@ -27,10 +28,10 @@ export function BulkActionBar({
|
|
|
27
28
|
errors?: string[]
|
|
28
29
|
} | null>(null)
|
|
29
30
|
|
|
30
|
-
const bulkPublish = useMutation(api.
|
|
31
|
-
const bulkUnpublish = useMutation(api.
|
|
32
|
-
const bulkDelete = useMutation(api.
|
|
33
|
-
const bulkUpdate = useMutation(api.
|
|
31
|
+
const bulkPublish = useMutation(api.bulkPublish)
|
|
32
|
+
const bulkUnpublish = useMutation(api.bulkUnpublish)
|
|
33
|
+
const bulkDelete = useMutation(api.bulkDelete)
|
|
34
|
+
const bulkUpdate = useMutation(api.bulkUpdate)
|
|
34
35
|
|
|
35
36
|
const handleAction = useCallback((action: BulkAction) => {
|
|
36
37
|
setActiveAction(action)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useRef } from 'react'
|
|
2
2
|
import { useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { FieldRenderer } from './fields/FieldRenderer'
|
|
5
5
|
import { VersionHistory } from './VersionHistory'
|
|
6
6
|
import type { FieldDefinition, FieldError } from './fields/types'
|
|
@@ -188,14 +188,15 @@ export function ContentEntryEditor({
|
|
|
188
188
|
const formDataRef = useRef(formData)
|
|
189
189
|
formDataRef.current = formData
|
|
190
190
|
|
|
191
|
-
const
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
const
|
|
191
|
+
const api = useApi()
|
|
192
|
+
const createEntry = useMutation(api.createEntry)
|
|
193
|
+
const updateEntry = useMutation(api.updateEntry)
|
|
194
|
+
const publishEntry = useMutation(api.publishEntry)
|
|
195
|
+
const unpublishEntry = useMutation(api.unpublishEntry)
|
|
196
|
+
const scheduleEntry = useMutation(api.scheduleEntry)
|
|
197
|
+
const cancelScheduleEntry = useMutation(api.cancelScheduledEntry)
|
|
198
|
+
const deleteEntryMutation = useMutation(api.deleteEntry)
|
|
199
|
+
const duplicateEntryMutation = useMutation(api.duplicateEntry)
|
|
199
200
|
|
|
200
201
|
const [showScheduleModal, setShowScheduleModal] = useState(false)
|
|
201
202
|
const [scheduleDateTime, setScheduleDateTime] = useState<string>(() => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useMemo, useEffect } from "react";
|
|
2
2
|
import { useMutation } from "convex/react";
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from "~/embed/contexts/ApiContext";
|
|
4
4
|
import type { FieldType, ContentType } from "convex-cms/types";
|
|
5
5
|
import { CmsDialog } from "~/components/cmsds/CmsDialog";
|
|
6
6
|
import { CmsButton } from "~/components/cmsds/CmsButton";
|
|
@@ -191,8 +191,9 @@ export function ContentTypeFormModal({
|
|
|
191
191
|
const [showBreakingWarning, setShowBreakingWarning] = useState(false);
|
|
192
192
|
const [isForceUpdating, setIsForceUpdating] = useState(false);
|
|
193
193
|
|
|
194
|
-
const
|
|
195
|
-
const
|
|
194
|
+
const api = useApi();
|
|
195
|
+
const createContentType = useMutation(api.createContentType);
|
|
196
|
+
const updateContentType = useMutation(api.updateContentType);
|
|
196
197
|
|
|
197
198
|
// Populate form when editing
|
|
198
199
|
useEffect(() => {
|
|
@@ -5,7 +5,7 @@ import { Layers, ChevronDown } from "lucide-react";
|
|
|
5
5
|
import { cn } from "~/lib/cn";
|
|
6
6
|
import { useAdminConfig } from "~/contexts";
|
|
7
7
|
import { Icon } from "~/lib/icons";
|
|
8
|
-
import {
|
|
8
|
+
import { useApi } from "~/embed/contexts/ApiContext";
|
|
9
9
|
import {
|
|
10
10
|
Collapsible,
|
|
11
11
|
CollapsibleTrigger,
|
|
@@ -19,10 +19,11 @@ export function Sidebar() {
|
|
|
19
19
|
const currentPath = routerState.location.pathname;
|
|
20
20
|
const config = useAdminConfig();
|
|
21
21
|
const { navItems, branding, layout } = config;
|
|
22
|
+
const api = useApi();
|
|
22
23
|
|
|
23
24
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
|
24
25
|
|
|
25
|
-
const contentTypesResult = useQuery(api.
|
|
26
|
+
const contentTypesResult = useQuery(api.listContentTypes, {
|
|
26
27
|
isActive: true,
|
|
27
28
|
});
|
|
28
29
|
const contentTypes = contentTypesResult?.page ?? [];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect } from 'react'
|
|
2
2
|
import { useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { CmsDialog } from '~/components/cmsds/CmsDialog'
|
|
5
5
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
6
6
|
import { Input } from '~/components/ui/input'
|
|
@@ -49,8 +49,9 @@ export function TaxonomyEditor({
|
|
|
49
49
|
const [submitError, setSubmitError] = useState<string | null>(null)
|
|
50
50
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false)
|
|
51
51
|
|
|
52
|
-
const
|
|
53
|
-
const
|
|
52
|
+
const api = useApi()
|
|
53
|
+
const createTaxonomy = useMutation(api.createTaxonomy)
|
|
54
|
+
const updateTaxonomy = useMutation(api.updateTaxonomy)
|
|
54
55
|
|
|
55
56
|
useEffect(() => {
|
|
56
57
|
if (taxonomy) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback } from 'react'
|
|
2
2
|
import { useQuery, useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { CmsDialog, CmsConfirmDialog } from '~/components/cmsds/CmsDialog'
|
|
5
5
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
6
6
|
import { CmsEmptyState } from '~/components/cmsds/CmsEmptyState'
|
|
@@ -34,6 +34,7 @@ export function TermTree({
|
|
|
34
34
|
isHierarchical,
|
|
35
35
|
allowInlineCreation,
|
|
36
36
|
}: TermTreeProps) {
|
|
37
|
+
const api = useApi()
|
|
37
38
|
const [expandedTerms, setExpandedTerms] = useState<Set<string>>(new Set())
|
|
38
39
|
const [editingTerm, setEditingTerm] = useState<Term | null>(null)
|
|
39
40
|
const [showCreateModal, setShowCreateModal] = useState(false)
|
|
@@ -42,10 +43,10 @@ export function TermTree({
|
|
|
42
43
|
const [error, setError] = useState<string | null>(null)
|
|
43
44
|
|
|
44
45
|
const termsQuery = isHierarchical
|
|
45
|
-
? useQuery(api.
|
|
46
|
-
: useQuery(api.
|
|
46
|
+
? useQuery(api.getTermsHierarchy, { taxonomyId })
|
|
47
|
+
: useQuery(api.listTerms, { taxonomyId })
|
|
47
48
|
|
|
48
|
-
const deleteTerm = useMutation(api.
|
|
49
|
+
const deleteTerm = useMutation(api.deleteTerm)
|
|
49
50
|
|
|
50
51
|
const terms = (
|
|
51
52
|
isHierarchical ? termsQuery : (termsQuery as { page?: Term[] })?.page
|
|
@@ -304,8 +305,9 @@ function TermEditModal({
|
|
|
304
305
|
const [submitError, setSubmitError] = useState<string | null>(null)
|
|
305
306
|
const [slugManuallyEdited, setSlugManuallyEdited] = useState(false)
|
|
306
307
|
|
|
307
|
-
const
|
|
308
|
-
const
|
|
308
|
+
const api = useApi()
|
|
309
|
+
const createTerm = useMutation(api.createTerm)
|
|
310
|
+
const updateTerm = useMutation(api.updateTerm)
|
|
309
311
|
|
|
310
312
|
const handleChange = useCallback(
|
|
311
313
|
(field: keyof typeof formData, value: string | number) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQuery } from 'convex/react'
|
|
2
|
-
import {
|
|
2
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
3
3
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
4
4
|
import { Badge } from '~/components/ui/badge'
|
|
5
5
|
import { ScrollArea } from '~/components/ui/scroll-area'
|
|
@@ -47,7 +47,8 @@ export function VersionCompare({
|
|
|
47
47
|
onClose,
|
|
48
48
|
onRollback,
|
|
49
49
|
}: VersionCompareProps) {
|
|
50
|
-
const
|
|
50
|
+
const api = useApi()
|
|
51
|
+
const comparisonQuery = useQuery(api.compareVersions, {
|
|
51
52
|
entryId,
|
|
52
53
|
fromVersionNumber: fromVersion,
|
|
53
54
|
toVersionNumber: toVersion,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback } from 'react'
|
|
2
2
|
import { useQuery, useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { VersionCompare } from './VersionCompare'
|
|
5
5
|
import { VersionRollbackModal } from './VersionRollbackModal'
|
|
6
6
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
@@ -34,6 +34,7 @@ export function VersionHistory({
|
|
|
34
34
|
onRollbackComplete,
|
|
35
35
|
onClose,
|
|
36
36
|
}: VersionHistoryProps) {
|
|
37
|
+
const api = useApi()
|
|
37
38
|
const [selectedVersions, setSelectedVersions] = useState<
|
|
38
39
|
[number, number] | null
|
|
39
40
|
>(null)
|
|
@@ -42,12 +43,12 @@ export function VersionHistory({
|
|
|
42
43
|
const [rollbackError, setRollbackError] = useState<string | null>(null)
|
|
43
44
|
const [rollbackSuccess, setRollbackSuccess] = useState(false)
|
|
44
45
|
|
|
45
|
-
const versionsQuery = useQuery(api.
|
|
46
|
+
const versionsQuery = useQuery(api.getVersionHistory, {
|
|
46
47
|
entryId,
|
|
47
48
|
paginationOpts: { numItems: 50, cursor: null },
|
|
48
49
|
})
|
|
49
50
|
|
|
50
|
-
const rollbackMutation = useMutation(api.
|
|
51
|
+
const rollbackMutation = useMutation(api.rollbackVersion)
|
|
51
52
|
|
|
52
53
|
const versions = (versionsQuery?.page ?? []) as VersionItem[]
|
|
53
54
|
const isLoading = versionsQuery === undefined
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useRef, useEffect } from 'react'
|
|
2
2
|
import { useQuery } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { FieldWrapper } from './FieldWrapper'
|
|
5
5
|
import type { BaseFieldProps } from './types'
|
|
6
6
|
import { asTaxonomyId } from '../../types'
|
|
@@ -41,6 +41,7 @@ export function CategoryField({
|
|
|
41
41
|
id,
|
|
42
42
|
placeholder = 'Select category...',
|
|
43
43
|
}: CategoryFieldProps) {
|
|
44
|
+
const api = useApi()
|
|
44
45
|
const fieldId = id || `field-${field.name}`
|
|
45
46
|
const taxonomyId = field.options?.taxonomyId
|
|
46
47
|
const allowMultiple = field.options?.allowMultiple ?? false
|
|
@@ -52,7 +53,7 @@ export function CategoryField({
|
|
|
52
53
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
53
54
|
|
|
54
55
|
const hierarchyResult = useQuery(
|
|
55
|
-
api.
|
|
56
|
+
api.getTermsHierarchy,
|
|
56
57
|
taxonomyId ? { taxonomyId: asTaxonomyId(taxonomyId) } : 'skip'
|
|
57
58
|
)
|
|
58
59
|
const categoryTree = (hierarchyResult ?? []) as CategoryTerm[]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback } from 'react'
|
|
2
2
|
import { useQuery } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
// IDs are strings when crossing component boundaries
|
|
5
5
|
import { FieldWrapper } from './FieldWrapper'
|
|
6
6
|
import type { BaseFieldProps } from './types'
|
|
@@ -96,6 +96,7 @@ export function MediaField({
|
|
|
96
96
|
id,
|
|
97
97
|
placeholder = 'Select media...',
|
|
98
98
|
}: MediaFieldProps) {
|
|
99
|
+
const api = useApi()
|
|
99
100
|
const fieldId = id || `field-${field.name}`
|
|
100
101
|
const [showPicker, setShowPicker] = useState(false)
|
|
101
102
|
const [activeTab, setActiveTab] = useState<string>('browse')
|
|
@@ -105,12 +106,12 @@ export function MediaField({
|
|
|
105
106
|
const allowedMimeTypes = field.options?.allowedMimeTypes ?? []
|
|
106
107
|
|
|
107
108
|
const selectedAsset = useQuery(
|
|
108
|
-
api.
|
|
109
|
+
api.getMediaAsset,
|
|
109
110
|
value ? { id: value } : 'skip'
|
|
110
111
|
)
|
|
111
112
|
|
|
112
113
|
const assetsResult = useQuery(
|
|
113
|
-
api.
|
|
114
|
+
api.listMediaAssets,
|
|
114
115
|
showPicker
|
|
115
116
|
? {
|
|
116
117
|
type: typeFilter
|
|
@@ -345,8 +346,8 @@ export function MediaField({
|
|
|
345
346
|
|
|
346
347
|
<TabsContent value="upload" className="mt-4">
|
|
347
348
|
<UploadDropzone
|
|
348
|
-
generateUploadUrl={api.
|
|
349
|
-
createAsset={api.
|
|
349
|
+
generateUploadUrl={api.generateUploadUrl}
|
|
350
|
+
createAsset={api.createMediaAsset}
|
|
350
351
|
onUploadComplete={handleUploadComplete}
|
|
351
352
|
allowedMimeTypes={allowedMimeTypes}
|
|
352
353
|
maxFileSize={field.options?.maxFileSize}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useMemo } from 'react'
|
|
2
2
|
import { useQuery } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { FieldWrapper } from './FieldWrapper'
|
|
5
5
|
import type { BaseFieldProps } from './types'
|
|
6
6
|
import {
|
|
@@ -62,6 +62,7 @@ export function ReferenceField({
|
|
|
62
62
|
id,
|
|
63
63
|
placeholder = 'Select content...',
|
|
64
64
|
}: ReferenceFieldProps) {
|
|
65
|
+
const api = useApi()
|
|
65
66
|
const fieldId = id || `field-${field.name}`
|
|
66
67
|
const [showPicker, setShowPicker] = useState(false)
|
|
67
68
|
const [searchQuery, setSearchQuery] = useState('')
|
|
@@ -75,7 +76,7 @@ export function ReferenceField({
|
|
|
75
76
|
return Array.isArray(value) ? value : [value]
|
|
76
77
|
}, [value])
|
|
77
78
|
|
|
78
|
-
const contentTypes = useQuery(api.
|
|
79
|
+
const contentTypes = useQuery(api.listContentTypes, {
|
|
79
80
|
isActive: true,
|
|
80
81
|
includeEntryCounts: false,
|
|
81
82
|
})
|
|
@@ -91,12 +92,12 @@ export function ReferenceField({
|
|
|
91
92
|
}, [contentTypes?.page, allowedContentTypes])
|
|
92
93
|
|
|
93
94
|
const selectedEntry = useQuery(
|
|
94
|
-
api.
|
|
95
|
+
api.getEntry,
|
|
95
96
|
selectedIds.length === 1 ? { id: selectedIds[0] } : 'skip'
|
|
96
97
|
)
|
|
97
98
|
|
|
98
99
|
const selectedEntries = useQuery(
|
|
99
|
-
api.
|
|
100
|
+
api.listEntries,
|
|
100
101
|
selectedIds.length > 1
|
|
101
102
|
? {
|
|
102
103
|
paginationOpts: { numItems: 100, cursor: null },
|
|
@@ -110,7 +111,7 @@ export function ReferenceField({
|
|
|
110
111
|
}, [selectedEntries?.page, selectedIds])
|
|
111
112
|
|
|
112
113
|
const entriesResult = useQuery(
|
|
113
|
-
api.
|
|
114
|
+
api.listEntries,
|
|
114
115
|
showPicker
|
|
115
116
|
? {
|
|
116
117
|
contentTypeName: contentTypeFilter || undefined,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useRef, useEffect, useId } from 'react'
|
|
2
2
|
import { useQuery, useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { FieldWrapper } from './FieldWrapper'
|
|
5
5
|
import type { BaseFieldProps } from './types'
|
|
6
6
|
import { asTaxonomyId, asTaxonomyTermIds } from '../../types'
|
|
@@ -34,6 +34,7 @@ export function TagField({
|
|
|
34
34
|
id,
|
|
35
35
|
placeholder = 'Add tags...',
|
|
36
36
|
}: TagFieldProps) {
|
|
37
|
+
const api = useApi()
|
|
37
38
|
const generatedId = useId()
|
|
38
39
|
const fieldId = id ?? `field-${field.name}-${generatedId}`
|
|
39
40
|
const taxonomyId = field.options?.taxonomyId
|
|
@@ -51,7 +52,7 @@ export function TagField({
|
|
|
51
52
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
52
53
|
|
|
53
54
|
const suggestionsResult = useQuery(
|
|
54
|
-
api.
|
|
55
|
+
api.suggestTerms,
|
|
55
56
|
taxonomyId
|
|
56
57
|
? {
|
|
57
58
|
taxonomyId: asTaxonomyId(taxonomyId),
|
|
@@ -64,7 +65,7 @@ export function TagField({
|
|
|
64
65
|
const suggestions = suggestionsResult ?? []
|
|
65
66
|
|
|
66
67
|
const selectedTermsResult = useQuery(
|
|
67
|
-
api.
|
|
68
|
+
api.listTerms,
|
|
68
69
|
taxonomyId && value && value.length > 0
|
|
69
70
|
? {
|
|
70
71
|
taxonomyId: asTaxonomyId(taxonomyId),
|
|
@@ -82,7 +83,7 @@ export function TagField({
|
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
const createTermMutation = useMutation(api.
|
|
86
|
+
const createTermMutation = useMutation(api.createTerm)
|
|
86
87
|
|
|
87
88
|
useEffect(() => {
|
|
88
89
|
function handleClickOutside(event: MouseEvent) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useMemo } from 'react'
|
|
2
2
|
import { useQuery } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
5
5
|
import {
|
|
6
6
|
Popover,
|
|
@@ -46,10 +46,11 @@ export function TaxonomyFilter({
|
|
|
46
46
|
disabled = false,
|
|
47
47
|
className,
|
|
48
48
|
}: TaxonomyFilterProps) {
|
|
49
|
+
const api = useApi()
|
|
49
50
|
const [open, setOpen] = useState(false)
|
|
50
51
|
const [search, setSearch] = useState('')
|
|
51
52
|
|
|
52
|
-
const taxonomiesResult = useQuery(api.
|
|
53
|
+
const taxonomiesResult = useQuery(api.listTaxonomies, { isActive: true })
|
|
53
54
|
const taxonomies = taxonomiesResult?.page ?? []
|
|
54
55
|
|
|
55
56
|
const activeTaxonomy = useMemo(() => {
|
|
@@ -62,7 +63,7 @@ export function TaxonomyFilter({
|
|
|
62
63
|
const targetTaxonomyId = taxonomyId ?? taxonomies[0]?._id
|
|
63
64
|
|
|
64
65
|
const termsResult = useQuery(
|
|
65
|
-
api.
|
|
66
|
+
api.listTerms,
|
|
66
67
|
targetTaxonomyId
|
|
67
68
|
? {
|
|
68
69
|
taxonomyId: targetTaxonomyId,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect } from 'react'
|
|
2
2
|
import { useMutation, useQuery } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { CmsDialog } from '~/components/cmsds/CmsDialog'
|
|
5
5
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
6
6
|
import { CmsField } from '~/components/cmsds/CmsField'
|
|
@@ -30,6 +30,7 @@ export function MediaAssetEditDialog({
|
|
|
30
30
|
onOpenChange,
|
|
31
31
|
onSaved,
|
|
32
32
|
}: MediaAssetEditDialogProps) {
|
|
33
|
+
const api = useApi()
|
|
33
34
|
const [name, setName] = useState('')
|
|
34
35
|
const [title, setTitle] = useState('')
|
|
35
36
|
const [description, setDescription] = useState('')
|
|
@@ -38,9 +39,9 @@ export function MediaAssetEditDialog({
|
|
|
38
39
|
const [isSaving, setIsSaving] = useState(false)
|
|
39
40
|
const [error, setError] = useState('')
|
|
40
41
|
|
|
41
|
-
const updateAsset = useMutation(api.
|
|
42
|
+
const updateAsset = useMutation(api.updateMediaAsset)
|
|
42
43
|
|
|
43
|
-
const taxonomiesResult = useQuery(api.
|
|
44
|
+
const taxonomiesResult = useQuery(api.listTaxonomies, {
|
|
44
45
|
isActive: true,
|
|
45
46
|
paginationOpts: { numItems: 50, cursor: null },
|
|
46
47
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect } from 'react'
|
|
2
2
|
import { useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { CmsDialog } from '~/components/cmsds/CmsDialog'
|
|
5
5
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
6
6
|
import { CmsField } from '~/components/cmsds/CmsField'
|
|
@@ -26,12 +26,13 @@ export function MediaFolderEditDialog({
|
|
|
26
26
|
onOpenChange,
|
|
27
27
|
onSaved,
|
|
28
28
|
}: MediaFolderEditDialogProps) {
|
|
29
|
+
const api = useApi()
|
|
29
30
|
const [name, setName] = useState('')
|
|
30
31
|
const [description, setDescription] = useState('')
|
|
31
32
|
const [isSaving, setIsSaving] = useState(false)
|
|
32
33
|
const [error, setError] = useState('')
|
|
33
34
|
|
|
34
|
-
const updateFolder = useMutation(api.
|
|
35
|
+
const updateFolder = useMutation(api.updateMediaFolder)
|
|
35
36
|
|
|
36
37
|
useEffect(() => {
|
|
37
38
|
if (folder) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useMemo } from 'react'
|
|
2
2
|
import { useQuery, useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { CmsDialog } from '~/components/cmsds/CmsDialog'
|
|
5
5
|
import { CmsButton } from '~/components/cmsds/CmsButton'
|
|
6
6
|
import { cn } from '~/lib/cn'
|
|
@@ -28,14 +28,15 @@ export function MediaMoveModal({
|
|
|
28
28
|
currentFolderId,
|
|
29
29
|
onMoved,
|
|
30
30
|
}: MediaMoveModalProps) {
|
|
31
|
+
const api = useApi()
|
|
31
32
|
const [selectedFolderId, setSelectedFolderId] = useState<string | undefined>(
|
|
32
33
|
undefined
|
|
33
34
|
)
|
|
34
35
|
const [isMoving, setIsMoving] = useState(false)
|
|
35
36
|
const [error, setError] = useState('')
|
|
36
37
|
|
|
37
|
-
const folderTree = useQuery(api.
|
|
38
|
-
const moveAssets = useMutation(api.
|
|
38
|
+
const folderTree = useQuery(api.getMediaFolderTree, {})
|
|
39
|
+
const moveAssets = useMutation(api.moveMediaAssets)
|
|
39
40
|
|
|
40
41
|
const sortedFolders = useMemo(() => {
|
|
41
42
|
if (!folderTree) return []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState, useCallback, useRef, useEffect } from 'react'
|
|
2
2
|
import { useQuery, useMutation } from 'convex/react'
|
|
3
|
-
import {
|
|
3
|
+
import { useApi } from '~/embed/contexts/ApiContext'
|
|
4
4
|
import { Badge } from '~/components/ui/badge'
|
|
5
5
|
import { Input } from '~/components/ui/input'
|
|
6
6
|
import { Button } from '~/components/ui/button'
|
|
@@ -32,6 +32,7 @@ export function MediaTaxonomyPicker({
|
|
|
32
32
|
disabled = false,
|
|
33
33
|
className = '',
|
|
34
34
|
}: MediaTaxonomyPickerProps) {
|
|
35
|
+
const api = useApi()
|
|
35
36
|
const [inputValue, setInputValue] = useState('')
|
|
36
37
|
const [showSuggestions, setShowSuggestions] = useState(false)
|
|
37
38
|
const [activeSuggestionIndex, setActiveSuggestionIndex] = useState(0)
|
|
@@ -42,14 +43,14 @@ export function MediaTaxonomyPicker({
|
|
|
42
43
|
const suggestionsRef = useRef<HTMLDivElement>(null)
|
|
43
44
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
44
45
|
|
|
45
|
-
const currentTerms = useQuery(api.
|
|
46
|
+
const currentTerms = useQuery(api.getTermsByMedia, {
|
|
46
47
|
mediaId,
|
|
47
48
|
taxonomyId,
|
|
48
49
|
})
|
|
49
50
|
|
|
50
51
|
const selectedTermIds = currentTerms?.map((t: TaxonomyTermDisplay) => t._id) ?? []
|
|
51
52
|
|
|
52
|
-
const suggestionsResult = useQuery(api.
|
|
53
|
+
const suggestionsResult = useQuery(api.suggestTerms, {
|
|
53
54
|
taxonomyId,
|
|
54
55
|
query: inputValue,
|
|
55
56
|
limit: 10,
|
|
@@ -57,8 +58,8 @@ export function MediaTaxonomyPicker({
|
|
|
57
58
|
})
|
|
58
59
|
const suggestions = (suggestionsResult ?? []) as TaxonomyTermDisplay[]
|
|
59
60
|
|
|
60
|
-
const setMediaTermsMutation = useMutation(api.
|
|
61
|
-
const createTermMutation = useMutation(api.
|
|
61
|
+
const setMediaTermsMutation = useMutation(api.setMediaTerms)
|
|
62
|
+
const createTermMutation = useMutation(api.createTermAndAddToMedia)
|
|
62
63
|
|
|
63
64
|
useEffect(() => {
|
|
64
65
|
function handleClickOutside(event: MouseEvent) {
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import { useQuery } from "convex/react";
|
|
2
|
+
import type { FunctionReference } from "convex/server";
|
|
2
3
|
import { createContext, useContext, useMemo, type ReactNode } from "react";
|
|
3
|
-
import { api as localApi } from "../../convex/_generated/api";
|
|
4
4
|
import type { AdminConfig } from "~/lib/admin-config";
|
|
5
5
|
import { AdminConfigProvider } from "./AdminConfigContext";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Settings returned by the getSettings query.
|
|
9
|
+
* This type is defined explicitly to avoid importing from convex/_generated.
|
|
10
|
+
*/
|
|
11
|
+
export interface Settings {
|
|
12
|
+
features: {
|
|
13
|
+
versioning: boolean;
|
|
14
|
+
scheduling: boolean;
|
|
15
|
+
localization: boolean;
|
|
16
|
+
mediaManagement: boolean;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
8
19
|
|
|
9
20
|
type SettingsApi = {
|
|
10
|
-
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
+
getSettings: FunctionReference<"query", "public", Record<string, never>, Settings | null>;
|
|
11
23
|
};
|
|
12
24
|
|
|
13
25
|
interface SettingsConfigContextValue {
|
|
@@ -26,8 +38,10 @@ export function SettingsConfigProvider({
|
|
|
26
38
|
children: ReactNode;
|
|
27
39
|
api?: SettingsApi;
|
|
28
40
|
}) {
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
// Use skip pattern when api is not provided
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
|
+
const queryArg = api ? api.getSettings : ("skip" as any);
|
|
44
|
+
const settings = useQuery(queryArg) as Settings | undefined;
|
|
31
45
|
|
|
32
46
|
const mergedConfig = useMemo((): AdminConfig => {
|
|
33
47
|
if (!settings) return baseConfig;
|
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { createContext, useContext, type ReactNode } from "react";
|
|
10
|
-
import {
|
|
10
|
+
import type { BaseAdminAPI } from "convex-cms";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
// CmsAdminApi accepts BaseAdminAPI with optional namespaced exports.
|
|
13
|
+
// This allows the API to work with Convex's FilterApi which removes
|
|
14
|
+
// non-FunctionReference types (the namespaced objects get filtered out).
|
|
15
|
+
type NamespacedKeys = "stats" | "settings" | "contentTypes" | "entries" | "bulk" | "trash" | "contentLock" | "versions" | "media" | "taxonomies";
|
|
16
|
+
export type CmsAdminApi = Omit<BaseAdminAPI, NamespacedKeys> & Partial<Pick<BaseAdminAPI, NamespacedKeys>>;
|
|
13
17
|
|
|
14
18
|
const ApiContext = createContext<CmsAdminApi | null>(null);
|
|
15
19
|
|
|
@@ -17,9 +17,11 @@ import {
|
|
|
17
17
|
type GetUserRoleHook,
|
|
18
18
|
type LogoutHook,
|
|
19
19
|
} from "~/contexts";
|
|
20
|
+
import { ApiProvider } from "~/embed/contexts/ApiContext";
|
|
20
21
|
import type { AdminConfig } from "~/lib/admin-config";
|
|
21
22
|
import { resolveAdminConfig } from "~/lib/admin-config";
|
|
22
23
|
import { getServerConfig, type ServerConfig } from "~/lib/config.server";
|
|
24
|
+
import { api } from "../../convex/_generated/api";
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Auth Configuration
|
|
@@ -228,9 +230,11 @@ function ConvexProviderWrapper({
|
|
|
228
230
|
|
|
229
231
|
return (
|
|
230
232
|
<ConvexProvider client={convex}>
|
|
231
|
-
<
|
|
232
|
-
{
|
|
233
|
-
|
|
233
|
+
<ApiProvider api={api.admin}>
|
|
234
|
+
<SettingsConfigProvider baseConfig={adminConfig}>
|
|
235
|
+
{children}
|
|
236
|
+
</SettingsConfigProvider>
|
|
237
|
+
</ApiProvider>
|
|
234
238
|
</ConvexProvider>
|
|
235
239
|
);
|
|
236
240
|
}
|
package/admin-dist/nitro.json
CHANGED