create-nextjs-cms 0.5.8

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.
Files changed (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +395 -0
  6. package/dist/lib/utils.d.ts +11 -0
  7. package/dist/lib/utils.d.ts.map +1 -0
  8. package/dist/lib/utils.js +48 -0
  9. package/package.json +44 -0
  10. package/templates/default/.env +24 -0
  11. package/templates/default/.env.development +8 -0
  12. package/templates/default/.eslintrc.json +5 -0
  13. package/templates/default/.prettierignore +7 -0
  14. package/templates/default/.prettierrc.json +19 -0
  15. package/templates/default/CHANGELOG.md +77 -0
  16. package/templates/default/README.md +45 -0
  17. package/templates/default/app/(auth)/auth/login/LoginPage.tsx +175 -0
  18. package/templates/default/app/(auth)/auth/login/page.tsx +12 -0
  19. package/templates/default/app/(rootLayout)/admins/page.tsx +5 -0
  20. package/templates/default/app/(rootLayout)/advanced/page.tsx +5 -0
  21. package/templates/default/app/(rootLayout)/analytics/page.tsx +7 -0
  22. package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +7 -0
  23. package/templates/default/app/(rootLayout)/categorized/[section]/page.tsx +7 -0
  24. package/templates/default/app/(rootLayout)/dashboard/page.tsx +7 -0
  25. package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +7 -0
  26. package/templates/default/app/(rootLayout)/emails/page.tsx +6 -0
  27. package/templates/default/app/(rootLayout)/layout.tsx +5 -0
  28. package/templates/default/app/(rootLayout)/loading.tsx +10 -0
  29. package/templates/default/app/(rootLayout)/log/page.tsx +7 -0
  30. package/templates/default/app/(rootLayout)/new/[section]/page.tsx +7 -0
  31. package/templates/default/app/(rootLayout)/page.tsx +9 -0
  32. package/templates/default/app/(rootLayout)/section/[section]/page.tsx +7 -0
  33. package/templates/default/app/(rootLayout)/settings/page.tsx +7 -0
  34. package/templates/default/app/_trpc/client.ts +4 -0
  35. package/templates/default/app/api/auth/csrf/route.ts +25 -0
  36. package/templates/default/app/api/auth/refresh/route.ts +10 -0
  37. package/templates/default/app/api/auth/route.ts +23 -0
  38. package/templates/default/app/api/auth/session/route.ts +20 -0
  39. package/templates/default/app/api/editor/photo/route.ts +42 -0
  40. package/templates/default/app/api/photo/route.ts +27 -0
  41. package/templates/default/app/api/placeholder/route.ts +7 -0
  42. package/templates/default/app/api/submit/section/item/[slug]/route.ts +63 -0
  43. package/templates/default/app/api/submit/section/item/route.ts +53 -0
  44. package/templates/default/app/api/submit/section/simple/route.ts +54 -0
  45. package/templates/default/app/api/trpc/[trpc]/route.ts +33 -0
  46. package/templates/default/app/api/video/route.ts +174 -0
  47. package/templates/default/app/dictionaries.ts +14 -0
  48. package/templates/default/app/layout.tsx +28 -0
  49. package/templates/default/app/providers.tsx +151 -0
  50. package/templates/default/cli.ts +4 -0
  51. package/templates/default/components/AdminCard.tsx +163 -0
  52. package/templates/default/components/AdminEditPage.tsx +123 -0
  53. package/templates/default/components/AdminPrivilegeCard.tsx +184 -0
  54. package/templates/default/components/AdminsPage.tsx +43 -0
  55. package/templates/default/components/AdvancedSettingsPage.tsx +167 -0
  56. package/templates/default/components/AnalyticsPage.tsx +127 -0
  57. package/templates/default/components/BarChartBox.tsx +43 -0
  58. package/templates/default/components/BrowsePage.tsx +119 -0
  59. package/templates/default/components/CategorizedSectionPage.tsx +36 -0
  60. package/templates/default/components/CategoryDeleteConfirmPage.tsx +129 -0
  61. package/templates/default/components/CategorySectionSelectInput.tsx +139 -0
  62. package/templates/default/components/ConditionalFields.tsx +49 -0
  63. package/templates/default/components/ContainerBox.tsx +24 -0
  64. package/templates/default/components/DashboardPage.tsx +187 -0
  65. package/templates/default/components/DashboardPageAlt.tsx +43 -0
  66. package/templates/default/components/DefaultNavItems.tsx +3 -0
  67. package/templates/default/components/Dropzone.tsx +153 -0
  68. package/templates/default/components/EmailCard.tsx +137 -0
  69. package/templates/default/components/EmailPasswordForm.tsx +84 -0
  70. package/templates/default/components/EmailQuotaForm.tsx +72 -0
  71. package/templates/default/components/EmailsPage.tsx +48 -0
  72. package/templates/default/components/GalleryPhoto.tsx +93 -0
  73. package/templates/default/components/InfoCard.tsx +94 -0
  74. package/templates/default/components/ItemEditPage.tsx +217 -0
  75. package/templates/default/components/Layout.tsx +70 -0
  76. package/templates/default/components/LoadingSpinners.tsx +67 -0
  77. package/templates/default/components/LogPage.tsx +17 -0
  78. package/templates/default/components/Modal.tsx +99 -0
  79. package/templates/default/components/Navbar.tsx +29 -0
  80. package/templates/default/components/NavbarAlt.tsx +182 -0
  81. package/templates/default/components/NewAdminForm.tsx +172 -0
  82. package/templates/default/components/NewEmailForm.tsx +131 -0
  83. package/templates/default/components/NewPage.tsx +206 -0
  84. package/templates/default/components/NewVariantComponent.tsx +228 -0
  85. package/templates/default/components/PhotoGallery.tsx +35 -0
  86. package/templates/default/components/PieChartBox.tsx +101 -0
  87. package/templates/default/components/ProgressBar.tsx +24 -0
  88. package/templates/default/components/ProtectedDocument.tsx +78 -0
  89. package/templates/default/components/ProtectedImage.tsx +143 -0
  90. package/templates/default/components/ProtectedVideo.tsx +76 -0
  91. package/templates/default/components/SectionItemCard.tsx +143 -0
  92. package/templates/default/components/SectionItemStatusBadge.tsx +16 -0
  93. package/templates/default/components/SectionPage.tsx +124 -0
  94. package/templates/default/components/SelectBox.tsx +99 -0
  95. package/templates/default/components/SelectInputButtons.tsx +124 -0
  96. package/templates/default/components/SettingsPage.tsx +238 -0
  97. package/templates/default/components/Sidebar.tsx +209 -0
  98. package/templates/default/components/SidebarDropdownItem.tsx +74 -0
  99. package/templates/default/components/SidebarItem.tsx +19 -0
  100. package/templates/default/components/TempPage.tsx +12 -0
  101. package/templates/default/components/ThemeProvider.tsx +8 -0
  102. package/templates/default/components/TooltipComponent.tsx +27 -0
  103. package/templates/default/components/VariantCard.tsx +123 -0
  104. package/templates/default/components/VariantEditPage.tsx +229 -0
  105. package/templates/default/components/analytics/BounceRate.tsx +69 -0
  106. package/templates/default/components/analytics/LivePageViews.tsx +54 -0
  107. package/templates/default/components/analytics/LiveUsersCount.tsx +32 -0
  108. package/templates/default/components/analytics/MonthlyPageViews.tsx +41 -0
  109. package/templates/default/components/analytics/TopCountries.tsx +51 -0
  110. package/templates/default/components/analytics/TopDevices.tsx +45 -0
  111. package/templates/default/components/analytics/TopMediums.tsx +57 -0
  112. package/templates/default/components/analytics/TopSources.tsx +44 -0
  113. package/templates/default/components/analytics/TotalPageViews.tsx +40 -0
  114. package/templates/default/components/analytics/TotalSessions.tsx +40 -0
  115. package/templates/default/components/analytics/TotalUniqueUsers.tsx +40 -0
  116. package/templates/default/components/custom/RightHomeRoomVariantCard.tsx +137 -0
  117. package/templates/default/components/dndKit/Draggable.tsx +21 -0
  118. package/templates/default/components/dndKit/Droppable.tsx +20 -0
  119. package/templates/default/components/dndKit/SortableItem.tsx +18 -0
  120. package/templates/default/components/form/DateRangeFormInput.tsx +55 -0
  121. package/templates/default/components/form/Form.tsx +298 -0
  122. package/templates/default/components/form/FormInputElement.tsx +68 -0
  123. package/templates/default/components/form/FormInputs.tsx +108 -0
  124. package/templates/default/components/form/helpers/util.ts +20 -0
  125. package/templates/default/components/form/inputs/CheckboxFormInput.tsx +33 -0
  126. package/templates/default/components/form/inputs/ColorFormInput.tsx +44 -0
  127. package/templates/default/components/form/inputs/DateFormInput.tsx +107 -0
  128. package/templates/default/components/form/inputs/DocumentFormInput.tsx +124 -0
  129. package/templates/default/components/form/inputs/MapFormInput.tsx +139 -0
  130. package/templates/default/components/form/inputs/MultipleSelectFormInput.tsx +150 -0
  131. package/templates/default/components/form/inputs/NumberFormInput.tsx +42 -0
  132. package/templates/default/components/form/inputs/PasswordFormInput.tsx +47 -0
  133. package/templates/default/components/form/inputs/PhotoFormInput.tsx +218 -0
  134. package/templates/default/components/form/inputs/RichTextFormInput.tsx +133 -0
  135. package/templates/default/components/form/inputs/SelectFormInput.tsx +164 -0
  136. package/templates/default/components/form/inputs/TagsFormInput.tsx +63 -0
  137. package/templates/default/components/form/inputs/TextFormInput.tsx +48 -0
  138. package/templates/default/components/form/inputs/TextareaFormInput.tsx +47 -0
  139. package/templates/default/components/form/inputs/VideoFormInput.tsx +117 -0
  140. package/templates/default/components/pagination/Pagination.tsx +36 -0
  141. package/templates/default/components/pagination/PaginationButtons.tsx +145 -0
  142. package/templates/default/components/ui/accordion.tsx +57 -0
  143. package/templates/default/components/ui/alert.tsx +46 -0
  144. package/templates/default/components/ui/badge.tsx +33 -0
  145. package/templates/default/components/ui/button.tsx +57 -0
  146. package/templates/default/components/ui/calendar.tsx +68 -0
  147. package/templates/default/components/ui/card.tsx +76 -0
  148. package/templates/default/components/ui/checkbox.tsx +29 -0
  149. package/templates/default/components/ui/dropdown-menu.tsx +205 -0
  150. package/templates/default/components/ui/input.tsx +25 -0
  151. package/templates/default/components/ui/label.tsx +26 -0
  152. package/templates/default/components/ui/popover.tsx +31 -0
  153. package/templates/default/components/ui/scroll-area.tsx +42 -0
  154. package/templates/default/components/ui/select.tsx +164 -0
  155. package/templates/default/components/ui/sheet.tsx +107 -0
  156. package/templates/default/components/ui/switch.tsx +29 -0
  157. package/templates/default/components/ui/table.tsx +120 -0
  158. package/templates/default/components/ui/tabs.tsx +55 -0
  159. package/templates/default/components/ui/toast.tsx +113 -0
  160. package/templates/default/components/ui/toaster.tsx +35 -0
  161. package/templates/default/components/ui/tooltip.tsx +30 -0
  162. package/templates/default/components/ui/use-toast.ts +188 -0
  163. package/templates/default/components.json +16 -0
  164. package/templates/default/context/ModalProvider.tsx +53 -0
  165. package/templates/default/drizzle.config.ts +4 -0
  166. package/templates/default/dynamic-schemas/schema.ts +373 -0
  167. package/templates/default/env/env.js +130 -0
  168. package/templates/default/envConfig.ts +4 -0
  169. package/templates/default/hooks/useModal.ts +8 -0
  170. package/templates/default/lib/apiHelpers.ts +106 -0
  171. package/templates/default/lz.config.ts +40 -0
  172. package/templates/default/middleware.ts +33 -0
  173. package/templates/default/next.config.ts +46 -0
  174. package/templates/default/package.json +134 -0
  175. package/templates/default/postcss.config.js +6 -0
  176. package/templates/default/postinstall.js +14 -0
  177. package/templates/default/public/blank_avatar.png +0 -0
  178. package/templates/default/public/favicon.ico +0 -0
  179. package/templates/default/public/img/placeholder.svg +1 -0
  180. package/templates/default/public/lazemni_logo.png +0 -0
  181. package/templates/default/public/next.svg +1 -0
  182. package/templates/default/public/vercel.svg +1 -0
  183. package/templates/default/section-tests.ts +92 -0
  184. package/templates/default/styles/globals.css +88 -0
  185. package/templates/default/tailwind.config.js +95 -0
  186. package/templates/default/test.ts +77 -0
  187. package/templates/default/tsconfig.json +44 -0
@@ -0,0 +1,77 @@
1
+ # cms
2
+
3
+ ## 0.5.8
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - nextjs-cms@0.5.8
9
+
10
+ ## 0.5.7
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+ - nextjs-cms@0.5.7
16
+
17
+ ## 0.5.6
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies
22
+ - nextjs-cms@0.5.6
23
+
24
+ ## 0.5.5
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies
29
+ - nextjs-cms@0.5.5
30
+
31
+ ## 0.5.4
32
+
33
+ ### Patch Changes
34
+
35
+ - Updated dependencies
36
+ - nextjs-cms@0.5.4
37
+
38
+ ## 0.5.3
39
+
40
+ ### Patch Changes
41
+
42
+ - Updated dependencies
43
+ - nextjs-cms@0.5.3
44
+
45
+ ## 0.5.2
46
+
47
+ ### Patch Changes
48
+
49
+ - Updated dependencies
50
+ - nextjs-cms@0.5.2
51
+
52
+ ## 0.5.1
53
+
54
+ ### Patch Changes
55
+
56
+ - Improved the create package.
57
+ - Updated dependencies
58
+ - nextjs-cms@0.5.1
59
+
60
+ ## 0.5.0
61
+
62
+ ### Minor Changes
63
+
64
+ - ff70c26: Refactored the next-cms to be one package.
65
+
66
+ Refactored and optimized all modules inside next-cms.
67
+
68
+ Added zod schemas to sections and fields classes and helper functions.
69
+
70
+ Added some props to the cms config.
71
+
72
+ Introduced unit testing and integration testing. (not done yet)
73
+
74
+ ### Patch Changes
75
+
76
+ - Updated dependencies [ff70c26]
77
+ - nextjs-cms@0.5.0
@@ -0,0 +1,45 @@
1
+ This is the official repository for LZCMS
2
+
3
+ LZCMS is an open-source content management system that is designed to be simple and easy to use. It is built with Next.js and Tailwind CSS.
4
+
5
+ ## Getting Started
6
+
7
+ First, run the development server:
8
+
9
+ ```bash
10
+ npm run dev
11
+ # or
12
+ yarn dev
13
+ # or
14
+ pnpm dev
15
+ # or
16
+ bun dev
17
+ ```
18
+
19
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
20
+
21
+ You can start adding sections to the cms by adding a new file in the `sections` directory. The file should end with `.section.ts` and should export a default object with the following properties:
22
+
23
+ ```tsx
24
+ export default {
25
+ name: 'Section Name',
26
+ slug: 'section-name',
27
+ fields: [
28
+ {
29
+ name: 'Field Name',
30
+ slug: 'field-name',
31
+ type: 'text',
32
+ required: true,
33
+ },
34
+ ],
35
+ };
36
+ ```
37
+
38
+
39
+ ## Learn More
40
+
41
+ To learn more about LZCMS, take a look at the following documentation:
42
+
43
+ - [LZCMS Documentation](https://lzcms.org/docs) - learn about lzcms features and API.
44
+
45
+ You can check out [the LZCMS GitHub repository](https://github.com/lzcms/lzcms/) - your feedback and contributions are welcome!
@@ -0,0 +1,175 @@
1
+ 'use client'
2
+
3
+ import React, { useEffect, useRef, useState } from 'react'
4
+ import { useRouter, useSearchParams } from 'next/navigation'
5
+ import getString from 'nextjs-cms/translations'
6
+ import InfoCard from '@/components/InfoCard'
7
+ import Link from 'next/link'
8
+ import { Switch } from '@/components/ui/switch'
9
+ import { Label } from '@/components/ui/label'
10
+ import { Button } from '@/components/ui/button'
11
+ import { MoonIcon, SunIcon } from '@radix-ui/react-icons'
12
+ import { useTheme } from 'next-themes'
13
+ import { login, useSession } from 'nextjs-cms/auth/react'
14
+
15
+ type fromErrors = {
16
+ username?: string | null
17
+ password?: string | null
18
+ general?: string | null
19
+ [key: string]: any
20
+ }
21
+
22
+ export default function LoginPage() {
23
+ const session = useSession()
24
+ const searchParams = useSearchParams()
25
+ const router = useRouter()
26
+ const loginButtonRef = useRef<HTMLButtonElement>(null)
27
+ const formRef = useRef<HTMLFormElement>(null)
28
+ const { setTheme } = useTheme()
29
+
30
+ const handleSubmit = async (event: React.FormEvent<HTMLButtonElement>) => {
31
+ event.preventDefault()
32
+ if (loginButtonRef.current) {
33
+ loginButtonRef.current.disabled = true
34
+ loginButtonRef.current.innerHTML = getString('loading')
35
+ }
36
+ try {
37
+ await login({
38
+ username: formRef.current?.username.value,
39
+ password: formRef.current?.password.value,
40
+ })
41
+ } catch (error: any) {
42
+ if (loginButtonRef.current) {
43
+ loginButtonRef.current.disabled = false
44
+ loginButtonRef.current.innerHTML = getString('login')
45
+ }
46
+
47
+ if (!error.message) {
48
+ setFormErrors({
49
+ general: getString('server_error'),
50
+ })
51
+ } else {
52
+ setFormErrors({ general: error.message })
53
+ }
54
+ }
55
+ }
56
+
57
+ const [formErrors, setFormErrors] = useState<fromErrors>({ username: null, password: null, general: null })
58
+
59
+ useEffect(() => {
60
+ if (session?.status === 'authenticated') {
61
+ const from = searchParams.get('callbackUrl')
62
+ if (from) {
63
+ router.push(from)
64
+ } else {
65
+ router.push('/')
66
+ }
67
+ }
68
+ }, [session])
69
+
70
+ return (
71
+ <>
72
+ <div className='fixed left-0 top-0 h-full w-full flex-1 flex-col justify-center overflow-auto bg-background px-6 py-12 text-foreground lg:px-8'>
73
+ <div className='flex w-full'>
74
+ <Button
75
+ variant='default'
76
+ onClick={() => {
77
+ setTheme((theme) => (theme === 'dark' ? 'light' : 'dark'))
78
+ }}
79
+ type='button'
80
+ className='absolute end-10 top-10 rounded-full p-3 focus:outline-none'
81
+ >
82
+ <span className='sr-only'>Theme</span>
83
+ <SunIcon className='hidden transition-all dark:block' aria-hidden='true' />
84
+ <MoonIcon className='transition-all dark:hidden' aria-hidden='true' />
85
+ </Button>
86
+ </div>
87
+ <div className='text-center sm:mx-auto sm:w-full sm:max-w-sm'>
88
+ <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:text-foreground hover:ring-0'>
89
+ LAZEMNI
90
+ </span>
91
+ <h2 className='mt-10 text-center text-2xl font-bold leading-9 tracking-tight'>
92
+ {getString('login_to_your_account')}
93
+ </h2>
94
+ </div>
95
+
96
+ <div className='mx-auto mt-10 w-full max-w-md rounded-lg bg-gradient-to-bl from-sky-50 to-green-50 p-12 shadow-lg ring-2 ring-inset ring-sky-400 dark:from-neutral-950 dark:to-neutral-800'>
97
+ <form ref={formRef} className='space-y-6'>
98
+ <div>
99
+ <label htmlFor='username' className='block text-sm font-medium leading-6'>
100
+ {getString('username')}
101
+ </label>
102
+ <div>
103
+ <input
104
+ id='username'
105
+ name='username'
106
+ type='text'
107
+ placeholder={getString('username')}
108
+ required
109
+ className='block w-full rounded-md border-0 bg-background p-3 text-foreground shadow-sm outline-0 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6'
110
+ />
111
+ </div>
112
+ </div>
113
+
114
+ <div>
115
+ <label htmlFor='password' className='block text-sm font-medium leading-6'>
116
+ {getString('password')}
117
+ </label>
118
+ <div>
119
+ <input
120
+ id='password'
121
+ name='password'
122
+ type='password'
123
+ placeholder={getString('password')}
124
+ required
125
+ className='block w-full rounded-md border-0 bg-background p-3 text-foreground shadow-sm outline-0 ring-1 ring-inset ring-sky-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6'
126
+ />
127
+ </div>
128
+ <div className='mt-2 text-end'>
129
+ <div className='text-sm'>
130
+ <Link href='#' className='font-semibold text-indigo-600 hover:text-indigo-500'>
131
+ {getString('forgot_password')}
132
+ </Link>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ <div>
137
+ <div className='flex items-center justify-between'>
138
+ <div className='flex gap-2'>
139
+ <div className='flex items-center space-x-2'>
140
+ <Switch id='remember_me_check' name='rm' />
141
+ <Label htmlFor='remember_me_check'>{getString('remember_me')}</Label>
142
+ </div>
143
+ </div>
144
+ </div>
145
+ <div className='mt-2'></div>
146
+ </div>
147
+
148
+ <div>
149
+ <Button
150
+ ref={loginButtonRef}
151
+ onClick={handleSubmit}
152
+ type='submit'
153
+ className='flex w-full justify-center rounded-md bg-gradient-to-r from-green-400 to-blue-500 font-extrabold hover:to-sky-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
154
+ >
155
+ {getString('login')}
156
+ </Button>
157
+ </div>
158
+ </form>
159
+ {Object.keys(formErrors).map((key, index) => {
160
+ if (formErrors[key]) {
161
+ return (
162
+ <div className='pt-3' key={index}>
163
+ <InfoCard
164
+ key={index}
165
+ result={{ key: 'danger', status: false, title: formErrors[key] }}
166
+ />
167
+ </div>
168
+ )
169
+ }
170
+ })}
171
+ </div>
172
+ </div>
173
+ </>
174
+ )
175
+ }
@@ -0,0 +1,12 @@
1
+ import LoginPage from './LoginPage'
2
+ import auth from 'nextjs-cms/auth'
3
+ import { redirect } from 'next/navigation'
4
+
5
+ // export const dynamic = 'force-dynamic'
6
+ export default async function Page() {
7
+ const session = await auth()
8
+ if (session) {
9
+ redirect('/')
10
+ }
11
+ return <LoginPage />
12
+ }
@@ -0,0 +1,5 @@
1
+ import AdminsPage from '@/components/AdminsPage'
2
+ // export const dynamic = 'force-dynamic'
3
+ export default async function Page() {
4
+ return <AdminsPage />
5
+ }
@@ -0,0 +1,5 @@
1
+ import AdvancedSettingsPage from '@/components/AdvancedSettingsPage'
2
+ // export const dynamic = 'force-dynamic'
3
+ export default async function Page() {
4
+ return <AdvancedSettingsPage />
5
+ }
@@ -0,0 +1,7 @@
1
+ import AnalyticsPage from '@/components/AnalyticsPage'
2
+
3
+ export const dynamic = 'force-dynamic'
4
+
5
+ export default async function Page() {
6
+ return <AnalyticsPage />
7
+ }
@@ -0,0 +1,7 @@
1
+ import BrowsePage from '@/components/BrowsePage'
2
+ type Params = Promise<{ section: string; page: string }>
3
+
4
+ export default async function Page(props: { params: Params }) {
5
+ const params = await props.params
6
+ return <BrowsePage page={params.page} section={params.section} />
7
+ }
@@ -0,0 +1,7 @@
1
+ import CategorizedSectionPage from '@/components/CategorizedSectionPage'
2
+ type Params = Promise<{ section: string }>
3
+
4
+ export default async function Page(props: { params: Params }) {
5
+ const params = await props.params
6
+ return <CategorizedSectionPage section={params.section} />
7
+ }
@@ -0,0 +1,7 @@
1
+ import DashboardPage from '@/components/DashboardPage'
2
+
3
+ export const dynamic = 'force-dynamic'
4
+
5
+ export default async function Page() {
6
+ return <DashboardPage />
7
+ }
@@ -0,0 +1,7 @@
1
+ import ItemEditPage from '@/components/ItemEditPage'
2
+ type Params = Promise<{ section: string; itemId: string }>
3
+
4
+ export default async function Page(props: { params: Params }) {
5
+ const params = await props.params
6
+ return <ItemEditPage sectionType='has_items' section={params.section} itemId={params.itemId} />
7
+ }
@@ -0,0 +1,6 @@
1
+ import EmailsPage from '@/components/EmailsPage'
2
+
3
+ export const dynamic = 'force-dynamic'
4
+ export default async function Page() {
5
+ return <EmailsPage />
6
+ }
@@ -0,0 +1,5 @@
1
+ import Layout from '@/components/Layout'
2
+
3
+ export default async function CMSLayout({ children }: { children: React.ReactNode }) {
4
+ return <Layout>{children}</Layout>
5
+ }
@@ -0,0 +1,10 @@
1
+ import LoadingSpinners from '@/components/LoadingSpinners'
2
+
3
+ export default function Loading() {
4
+ // You can add any UI inside Loading, including a Skeleton.
5
+ return (
6
+ <div className='p-20'>
7
+ <LoadingSpinners />
8
+ </div>
9
+ )
10
+ }
@@ -0,0 +1,7 @@
1
+ import LogPage from '@/components/LogPage'
2
+
3
+ export const dynamic = 'force-dynamic'
4
+
5
+ export default async function Page() {
6
+ return <LogPage />
7
+ }
@@ -0,0 +1,7 @@
1
+ import NewPage from '@/components/NewPage'
2
+ type Params = Promise<{ section: string }>
3
+
4
+ export default async function Page(props: { params: Params }) {
5
+ const params = await props.params
6
+ return <NewPage sectionType='has_items' section={params.section} />
7
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react'
2
+
3
+ import Dashboard from './dashboard/page'
4
+
5
+ export const dynamic = 'force-dynamic'
6
+
7
+ export default function Home() {
8
+ return <Dashboard />
9
+ }
@@ -0,0 +1,7 @@
1
+ import SectionPage from '@/components/SectionPage'
2
+ type Params = Promise<{ section: string }>
3
+
4
+ export default async function Page(props: { params: Params }) {
5
+ const params = await props.params
6
+ return <SectionPage section={params.section} />
7
+ }
@@ -0,0 +1,7 @@
1
+ import SettingsPage from '@/components/SettingsPage'
2
+
3
+ export const dynamic = 'force-dynamic'
4
+
5
+ export default async function Page() {
6
+ return <SettingsPage />
7
+ }
@@ -0,0 +1,4 @@
1
+ import type { AppRouter } from 'nextjs-cms/api'
2
+ import { createTRPCReact} from '@trpc/react-query'
3
+
4
+ export const trpc = createTRPCReact<AppRouter>()
@@ -0,0 +1,25 @@
1
+ import { responseHeaders } from 'nextjs-cms/utils'
2
+ import { createCSRFToken } from 'nextjs-cms/auth/actions'
3
+ import { cookies } from 'next/headers'
4
+
5
+ export async function GET() {
6
+ const cookieStore = await cookies()
7
+ const csrfTokenCookie = cookieStore.get('csrf_token')
8
+ const { csrfToken, cookie } = await createCSRFToken(csrfTokenCookie?.value)
9
+
10
+ if (cookie) {
11
+ (await cookies()).set({
12
+ name: 'csrf_token',
13
+ value: cookie,
14
+ httpOnly: true,
15
+ secure: true,
16
+ sameSite: true,
17
+ })
18
+ }
19
+ return Response.json(
20
+ {
21
+ csrfToken,
22
+ },
23
+ responseHeaders,
24
+ )
25
+ }
@@ -0,0 +1,10 @@
1
+ import { NextRequest } from 'next/server'
2
+ import { authRefresh } from 'nextjs-cms/auth/actions'
3
+
4
+ export async function GET(request: NextRequest) {
5
+ const refreshToken = request.cookies.get('refresh_token')
6
+ const loginResult = await authRefresh(refreshToken)
7
+ return Response.json(loginResult, {
8
+ status: loginResult.status,
9
+ })
10
+ }
@@ -0,0 +1,23 @@
1
+ import { NextRequest } from 'next/server'
2
+ import auth from 'nextjs-cms/auth'
3
+ import { deleteSession, login } from 'nextjs-cms/auth/actions'
4
+
5
+ export async function POST(request: NextRequest) {
6
+ const { username, password } = await request.json()
7
+ try {
8
+ const loginResult = await login({ username, password })
9
+ return Response.json(loginResult, { status: 200 })
10
+ } catch (error: any) {
11
+ return Response.json({ error: error.message }, { status: 400 })
12
+ }
13
+ }
14
+
15
+ export async function DELETE() {
16
+ const session = await auth()
17
+ try {
18
+ const loginResult = await deleteSession(session)
19
+ return Response.json(loginResult, { status: 200 })
20
+ } catch (error: any) {
21
+ return Response.json({ error: error.message }, { status: 400 })
22
+ }
23
+ }
@@ -0,0 +1,20 @@
1
+ import auth from 'nextjs-cms/auth'
2
+ import { NextRequest } from 'next/server'
3
+
4
+ export async function GET(request: NextRequest) {
5
+ const session = await auth()
6
+ return Response.json(session, {
7
+ status: session ? 200 : 404,
8
+ })
9
+ }
10
+
11
+ export async function POST(request: NextRequest) {
12
+ const session = await auth()
13
+ if (!session) {
14
+ return Response.json('Unauthorized', { status: 401 })
15
+ }
16
+
17
+ // TODO: Handle POST request to update session with new data
18
+
19
+ return Response.json(session)
20
+ }
@@ -0,0 +1,42 @@
1
+ import { NextRequest, NextResponse } from 'next/server'
2
+ import sharp from 'sharp'
3
+ import auth from 'nextjs-cms/auth'
4
+
5
+ export async function POST(request: NextRequest) {
6
+ const session = await auth()
7
+
8
+ if (!session || !session.user) {
9
+ return NextResponse.json(
10
+ {
11
+ error: 'Access token not provided',
12
+ },
13
+ { status: 401 },
14
+ )
15
+ }
16
+
17
+ const formData = await request.formData()
18
+ const photo = formData.get('photo') as File
19
+
20
+ if (!photo) {
21
+ return NextResponse.json(
22
+ {
23
+ error: 'Photo not provided',
24
+ },
25
+ { status: 400 },
26
+ )
27
+ }
28
+
29
+ const arrayBuffer = await photo.arrayBuffer()
30
+ const buffer = Buffer.from(arrayBuffer)
31
+
32
+ sharp.cache({ files: 0 })
33
+ sharp.cache(false)
34
+ const image = sharp(buffer)
35
+
36
+ let webpBuffer = await image.toFormat('webp').resize(1200, 768).withExif({}).toBuffer()
37
+
38
+ const base64String = webpBuffer.toString('base64')
39
+ image.destroy()
40
+
41
+ return NextResponse.json(`data:image/webp;base64,${base64String}`)
42
+ }
@@ -0,0 +1,27 @@
1
+ import { NextRequest, NextResponse } from 'next/server'
2
+ import { getPhoto } from 'nextjs-cms/api/helpers'
3
+
4
+ export async function GET(request: NextRequest) {
5
+ const searchParams = request.nextUrl.searchParams
6
+
7
+ const name = searchParams.get('name')
8
+ const folder = searchParams.get('folder')
9
+ const isThumb = searchParams.get('isThumb')
10
+
11
+ if (!name || !folder || !isThumb) {
12
+ return NextResponse.json(
13
+ {
14
+ error: 'Invalid request',
15
+ },
16
+ { status: 400 },
17
+ )
18
+ }
19
+
20
+ const base64String = await getPhoto({
21
+ name,
22
+ folder,
23
+ isThumb: isThumb === 'true',
24
+ })
25
+
26
+ return NextResponse.json(base64String)
27
+ }
@@ -0,0 +1,7 @@
1
+ import { NextRequest } from 'next/server'
2
+ // import { getPlaiceholder } from 'plaiceholder'
3
+ import { responseHeaders } from 'nextjs-cms/utils'
4
+
5
+ export async function GET(request: NextRequest) {
6
+ return Response.json(null, responseHeaders)
7
+ }