create-nextjs-cms 0.5.67 → 0.5.68
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/package.json +1 -1
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/PluginClient.tsx +55 -0
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/page.tsx +41 -0
- package/templates/default/app/(rootLayout)/(plugins)/[...slug]/plugin-registry.ts +16 -0
- package/templates/default/app/(rootLayout)/page.tsx +6 -5
- package/templates/default/app/_trpc/client.ts +1 -1
- package/templates/default/app/api/trpc/[trpc]/route.ts +3 -3
- package/templates/default/cms.config.ts +1 -2
- package/templates/default/components/AdminCard.tsx +1 -1
- package/templates/default/components/AdminPrivilegeCard.tsx +1 -1
- package/templates/default/components/CategorySectionSelectInput.tsx +1 -1
- package/templates/default/components/DashboardPage.tsx +1 -1
- package/templates/default/components/EmailCard.tsx +1 -1
- package/templates/default/components/EmailPasswordForm.tsx +1 -1
- package/templates/default/components/EmailQuotaForm.tsx +1 -1
- package/templates/default/components/EmailsPage.tsx +1 -1
- package/templates/default/components/NewAdminForm.tsx +1 -1
- package/templates/default/components/NewEmailForm.tsx +1 -1
- package/templates/default/components/SectionItemCard.tsx +1 -1
- package/templates/default/components/Sidebar.tsx +1 -1
- package/templates/default/components/form/Form.tsx +1 -1
- package/templates/default/components/form/helpers/_section-hot-reload.js +1 -1
- package/templates/default/package.json +2 -2
- package/templates/default/app/(rootLayout)/analytics/page.tsx +0 -7
- package/templates/default/app/(rootLayout)/dashboard/page.tsx +0 -7
- package/templates/default/app/(rootLayout)/emails/page.tsx +0 -6
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import dynamic from 'next/dynamic'
|
|
4
|
+
import React, { useMemo } from 'react'
|
|
5
|
+
import { trpc } from '@/app/_trpc/client'
|
|
6
|
+
import { getPluginClientLoader } from './plugin-registry'
|
|
7
|
+
|
|
8
|
+
type PluginClientProps = {
|
|
9
|
+
packageName: string
|
|
10
|
+
component: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const isComponentType = (value: unknown): value is React.ComponentType<any> => {
|
|
14
|
+
if (typeof value === 'function') return true
|
|
15
|
+
if (typeof value === 'object' && value !== null && '$$typeof' in value) return true
|
|
16
|
+
return false
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function PluginClient({ packageName, component }: PluginClientProps) {
|
|
20
|
+
const loader = getPluginClientLoader(packageName)
|
|
21
|
+
if (!loader) {
|
|
22
|
+
return <div className='text-destructive p-6 text-sm'>Plugin client package not registered: {packageName}</div>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const Component = useMemo(
|
|
26
|
+
() =>
|
|
27
|
+
dynamic(
|
|
28
|
+
async () => {
|
|
29
|
+
const mod = await loader()
|
|
30
|
+
const resolved =
|
|
31
|
+
(mod.components && mod.components[component]) ||
|
|
32
|
+
(mod as Record<string, React.ComponentType<any>>)[component] ||
|
|
33
|
+
mod.default
|
|
34
|
+
|
|
35
|
+
if (!resolved || !isComponentType(resolved)) {
|
|
36
|
+
return {
|
|
37
|
+
default: () => (
|
|
38
|
+
<div className='text-destructive p-6 text-sm'>
|
|
39
|
+
Plugin component not found: {component}
|
|
40
|
+
</div>
|
|
41
|
+
),
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { default: resolved }
|
|
46
|
+
},
|
|
47
|
+
{ ssr: false },
|
|
48
|
+
),
|
|
49
|
+
[component, loader],
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
return <Component trpc={trpc} />
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default PluginClient
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { notFound, redirect } from 'next/navigation'
|
|
2
|
+
import { api, HydrateClient } from 'nextjs-cms/api/trpc/server'
|
|
3
|
+
import { findPluginRouteByPath } from 'nextjs-cms/plugins/server'
|
|
4
|
+
import PluginClient from './PluginClient'
|
|
5
|
+
|
|
6
|
+
export const dynamic = 'force-dynamic'
|
|
7
|
+
type Params = Promise<{ slug?: string[] }>
|
|
8
|
+
|
|
9
|
+
export default async function Page(props: { params: Params }) {
|
|
10
|
+
const params = await props.params
|
|
11
|
+
const slug = params.slug ?? []
|
|
12
|
+
|
|
13
|
+
if (slug[0] === 'plugin') {
|
|
14
|
+
const rest = slug.slice(1)
|
|
15
|
+
if (rest.length === 0) {
|
|
16
|
+
const routes = await api.plugins.routes()
|
|
17
|
+
const target = routes[0]?.path
|
|
18
|
+
if (target) {
|
|
19
|
+
redirect(target)
|
|
20
|
+
}
|
|
21
|
+
notFound()
|
|
22
|
+
}
|
|
23
|
+
redirect(`/${rest.join('/')}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const path = `/${slug.join('/')}`
|
|
27
|
+
const route = await findPluginRouteByPath(path)
|
|
28
|
+
if (!route) {
|
|
29
|
+
notFound()
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (route.prefetch) {
|
|
33
|
+
await route.prefetch({ api })
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<HydrateClient>
|
|
38
|
+
<PluginClient packageName={route.pluginId} component={route.component} />
|
|
39
|
+
</HydrateClient>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentType } from 'react'
|
|
2
|
+
|
|
3
|
+
export type PluginClientComponent = ComponentType<any>
|
|
4
|
+
|
|
5
|
+
export type PluginClientModule = {
|
|
6
|
+
components?: Record<string, PluginClientComponent>
|
|
7
|
+
default?: unknown
|
|
8
|
+
[key: string]: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type PluginClientLoader = () => Promise<PluginClientModule>
|
|
12
|
+
|
|
13
|
+
// Keep this list in sync with cms.config.ts and apps/cms/package.json.
|
|
14
|
+
const pluginClientLoaders: Record<string, PluginClientLoader> = {}
|
|
15
|
+
|
|
16
|
+
export const getPluginClientLoader = (packageName: string) => pluginClientLoaders[packageName]
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import Dashboard from './dashboard/page'
|
|
1
|
+
import { redirect } from 'next/navigation'
|
|
2
|
+
import { getPluginRoutes } from 'nextjs-cms/plugins/server'
|
|
4
3
|
|
|
5
4
|
export const dynamic = 'force-dynamic'
|
|
6
5
|
|
|
7
|
-
export default function Home() {
|
|
8
|
-
|
|
6
|
+
export default async function Home() {
|
|
7
|
+
const routes = await getPluginRoutes()
|
|
8
|
+
const target = routes[0]?.path ?? '/admins'
|
|
9
|
+
redirect(target)
|
|
9
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
|
|
2
|
-
import {
|
|
2
|
+
import { createTRPCContext, getAppRouter } from 'nextjs-cms/api'
|
|
3
3
|
import { NextRequest } from 'next/server'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -13,11 +13,11 @@ const context = async (req: NextRequest) => {
|
|
|
13
13
|
})
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const handler = (req: NextRequest) =>
|
|
16
|
+
const handler = async (req: NextRequest) =>
|
|
17
17
|
fetchRequestHandler({
|
|
18
18
|
endpoint: '/api/trpc',
|
|
19
19
|
req,
|
|
20
|
-
router:
|
|
20
|
+
router: await getAppRouter(),
|
|
21
21
|
createContext: () => context(req),
|
|
22
22
|
/*onError(opts) {
|
|
23
23
|
return opts.error
|
|
@@ -2,8 +2,7 @@ import type { CMSConfig } from 'nextjs-cms/core/config'
|
|
|
2
2
|
import process from 'process'
|
|
3
3
|
import { resolve } from 'path'
|
|
4
4
|
|
|
5
|
-
export const config: CMSConfig = {
|
|
6
|
-
ui: {
|
|
5
|
+
export const config: CMSConfig = {
|
|
7
6
|
title: 'NEXT CMS Admin',
|
|
8
7
|
defaultTheme: 'dark',
|
|
9
8
|
logo: '/logo.svg',
|
|
@@ -9,7 +9,7 @@ import { Badge } from '@/components/ui/badge'
|
|
|
9
9
|
import { Button } from '@/components/ui/button'
|
|
10
10
|
import { trpc } from '@/app/_trpc/client'
|
|
11
11
|
import Image from 'next/image'
|
|
12
|
-
import { RouterOutputs } from 'nextjs-cms/api'
|
|
12
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
13
13
|
|
|
14
14
|
export default function AdminCard({
|
|
15
15
|
admin,
|
|
@@ -5,7 +5,7 @@ import React, { useEffect } from 'react'
|
|
|
5
5
|
import getString from 'nextjs-cms/translations'
|
|
6
6
|
import { Badge } from '@/components/ui/badge'
|
|
7
7
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
8
|
-
import { RouterOutputs } from 'nextjs-cms/api'
|
|
8
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
9
9
|
|
|
10
10
|
export default function AdminRoleCard({
|
|
11
11
|
privilege,
|
|
@@ -7,7 +7,7 @@ import SelectInputButtons from '@/components/SelectInputButtons'
|
|
|
7
7
|
import getString from 'nextjs-cms/translations'
|
|
8
8
|
import { trpc } from '@/app/_trpc/client'
|
|
9
9
|
import { SelectOption } from 'nextjs-cms/core/fields'
|
|
10
|
-
import { RouterOutputs } from 'nextjs-cms/api'
|
|
10
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
11
11
|
import { nanoid } from 'nanoid'
|
|
12
12
|
|
|
13
13
|
type CategorySelect = RouterOutputs['categorySections']['get']['data']
|
|
@@ -11,7 +11,7 @@ import { trpc } from '@/app/_trpc/client'
|
|
|
11
11
|
ChartJS.register(ArcElement, Tooltip, Legend)
|
|
12
12
|
|
|
13
13
|
const DashboardPage = () => {
|
|
14
|
-
const { isLoading, isError, data, error } = trpc.
|
|
14
|
+
const { isLoading, isError, data, error } = trpc.cpanelDashboard.getData.useQuery()
|
|
15
15
|
|
|
16
16
|
useEffect(() => {}, [])
|
|
17
17
|
|
|
@@ -14,7 +14,7 @@ export default function EmailCard({ email, action }: { email: EmailItem; action:
|
|
|
14
14
|
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
15
15
|
const { toast } = useToast()
|
|
16
16
|
|
|
17
|
-
const deleteMutation = trpc.
|
|
17
|
+
const deleteMutation = trpc.cpanelEmails.deleteEmail.useMutation({
|
|
18
18
|
onError: (error) => {
|
|
19
19
|
setModalResponse({
|
|
20
20
|
message: error.message,
|
|
@@ -9,7 +9,7 @@ export default function EmailPasswordForm({ email, action }: { email: string; ac
|
|
|
9
9
|
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
10
10
|
|
|
11
11
|
const { toast } = useToast()
|
|
12
|
-
const quotaMutation = trpc.
|
|
12
|
+
const quotaMutation = trpc.cpanelEmails.passwordChange.useMutation({
|
|
13
13
|
onError: (error) => {
|
|
14
14
|
setModal({
|
|
15
15
|
title: getString('error'),
|
|
@@ -10,7 +10,7 @@ export default function EmailQuotaForm({ email, action }: { email: string; actio
|
|
|
10
10
|
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
11
11
|
const { toast } = useToast()
|
|
12
12
|
|
|
13
|
-
const quotaMutation = trpc.
|
|
13
|
+
const quotaMutation = trpc.cpanelEmails.quotaChange.useMutation({
|
|
14
14
|
onError: (error) => {
|
|
15
15
|
setModal({
|
|
16
16
|
title: getString('error'),
|
|
@@ -11,7 +11,7 @@ import { trpc } from '@/app/_trpc/client'
|
|
|
11
11
|
const EmailsPage = () => {
|
|
12
12
|
const controller = new AbortController()
|
|
13
13
|
|
|
14
|
-
const { isLoading, isError, data, error, refetch } = trpc.
|
|
14
|
+
const { isLoading, isError, data, error, refetch } = trpc.cpanelEmails.getEmails.useQuery()
|
|
15
15
|
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
return () => {
|
|
@@ -6,7 +6,7 @@ import { useToast } from '@/components/ui/use-toast'
|
|
|
6
6
|
import { trpc } from '@/app/_trpc/client'
|
|
7
7
|
import AdminRoleCard from '@/components/AdminPrivilegeCard'
|
|
8
8
|
import { Button } from '@/components/ui/button'
|
|
9
|
-
import { RouterOutputs } from 'nextjs-cms/api'
|
|
9
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
10
10
|
|
|
11
11
|
export default function NewAdminForm({
|
|
12
12
|
privileges,
|
|
@@ -10,7 +10,7 @@ export default function NewEmailForm({ action }: { action: any }) {
|
|
|
10
10
|
const { setModal, modal, modalResponse, setModalResponse } = useModal()
|
|
11
11
|
const formRef = React.useRef<HTMLFormElement>(null)
|
|
12
12
|
const { toast } = useToast()
|
|
13
|
-
const newEmailMutation = trpc.
|
|
13
|
+
const newEmailMutation = trpc.cpanelEmails.createEmail.useMutation({
|
|
14
14
|
onError: (error) => {
|
|
15
15
|
setModal({
|
|
16
16
|
title: getString('error'),
|
|
@@ -9,7 +9,7 @@ import { CardTitle, CardHeader, CardFooter, Card, CardContent } from '@/componen
|
|
|
9
9
|
import { Button } from '@/components/ui/button'
|
|
10
10
|
import { PersonIcon } from '@radix-ui/react-icons'
|
|
11
11
|
import { trpc } from '@/app/_trpc/client'
|
|
12
|
-
import { RouterOutputs } from 'nextjs-cms/api'
|
|
12
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
13
13
|
|
|
14
14
|
// Used to get elements of array types as types
|
|
15
15
|
type ArrElement<ArrType> = ArrType extends readonly (infer ElementType)[] ? ElementType : never
|
|
@@ -51,7 +51,7 @@ const Sidebar = (props: SidebarProps) => {
|
|
|
51
51
|
'justify-between p-4': true,
|
|
52
52
|
})}
|
|
53
53
|
>
|
|
54
|
-
<span className='bg-gray-800 px-2 font-bold tracking-tighter text-amber-200 ring-1 ring-sky-500 transition-all duration-150 hover:bg-transparent hover:font-normal hover:tracking-[1em] hover:ring-0'>
|
|
54
|
+
<span className='bg-gray-800 px-2 font-bold tracking-tighter text-amber-200 ring-1 ring-sky-500 transition-all duration-150 hover:bg-transparent hover:font-normal hover:tracking-[0.1em] hover:ring-0'>
|
|
55
55
|
nextjs-cms
|
|
56
56
|
</span>
|
|
57
57
|
</div>
|
|
@@ -8,7 +8,7 @@ import NewVariantComponent, { VariantHandles } from '@/components/NewVariantComp
|
|
|
8
8
|
import classNames from 'classnames'
|
|
9
9
|
import ProgressBar from '@/components/ProgressBar'
|
|
10
10
|
import React, { RefObject, useEffect } from 'react'
|
|
11
|
-
import { RouterOutputs } from 'nextjs-cms/api'
|
|
11
|
+
import type { RouterOutputs } from 'nextjs-cms/api'
|
|
12
12
|
import * as z from 'zod'
|
|
13
13
|
import { zodResolver } from '@hookform/resolvers/zod'
|
|
14
14
|
import { useForm, FormProvider } from 'react-hook-form'
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"nanoid": "^5.1.2",
|
|
65
65
|
"next": "16.1.1",
|
|
66
66
|
"next-themes": "^0.4.6",
|
|
67
|
-
"nextjs-cms": "0.5.
|
|
67
|
+
"nextjs-cms": "0.5.68",
|
|
68
68
|
"plaiceholder": "^3.0.0",
|
|
69
69
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
|
70
70
|
"qrcode": "^1.5.4",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"eslint-config-prettier": "^10.0.1",
|
|
98
98
|
"eslint-plugin-prettier": "^5.2.3",
|
|
99
99
|
"fs-extra": "^11.3.3",
|
|
100
|
-
"nextjs-cms-kit": "0.5.
|
|
100
|
+
"nextjs-cms-kit": "0.5.68",
|
|
101
101
|
"postcss": "^8.5.1",
|
|
102
102
|
"prettier": "3.5.0",
|
|
103
103
|
"raw-loader": "^4.0.2",
|