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.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +395 -0
- package/dist/lib/utils.d.ts +11 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +48 -0
- package/package.json +44 -0
- package/templates/default/.env +24 -0
- package/templates/default/.env.development +8 -0
- package/templates/default/.eslintrc.json +5 -0
- package/templates/default/.prettierignore +7 -0
- package/templates/default/.prettierrc.json +19 -0
- package/templates/default/CHANGELOG.md +77 -0
- package/templates/default/README.md +45 -0
- package/templates/default/app/(auth)/auth/login/LoginPage.tsx +175 -0
- package/templates/default/app/(auth)/auth/login/page.tsx +12 -0
- package/templates/default/app/(rootLayout)/admins/page.tsx +5 -0
- package/templates/default/app/(rootLayout)/advanced/page.tsx +5 -0
- package/templates/default/app/(rootLayout)/analytics/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/browse/[section]/[page]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/categorized/[section]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/dashboard/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/edit/[section]/[itemId]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/emails/page.tsx +6 -0
- package/templates/default/app/(rootLayout)/layout.tsx +5 -0
- package/templates/default/app/(rootLayout)/loading.tsx +10 -0
- package/templates/default/app/(rootLayout)/log/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/new/[section]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/page.tsx +9 -0
- package/templates/default/app/(rootLayout)/section/[section]/page.tsx +7 -0
- package/templates/default/app/(rootLayout)/settings/page.tsx +7 -0
- package/templates/default/app/_trpc/client.ts +4 -0
- package/templates/default/app/api/auth/csrf/route.ts +25 -0
- package/templates/default/app/api/auth/refresh/route.ts +10 -0
- package/templates/default/app/api/auth/route.ts +23 -0
- package/templates/default/app/api/auth/session/route.ts +20 -0
- package/templates/default/app/api/editor/photo/route.ts +42 -0
- package/templates/default/app/api/photo/route.ts +27 -0
- package/templates/default/app/api/placeholder/route.ts +7 -0
- package/templates/default/app/api/submit/section/item/[slug]/route.ts +63 -0
- package/templates/default/app/api/submit/section/item/route.ts +53 -0
- package/templates/default/app/api/submit/section/simple/route.ts +54 -0
- package/templates/default/app/api/trpc/[trpc]/route.ts +33 -0
- package/templates/default/app/api/video/route.ts +174 -0
- package/templates/default/app/dictionaries.ts +14 -0
- package/templates/default/app/layout.tsx +28 -0
- package/templates/default/app/providers.tsx +151 -0
- package/templates/default/cli.ts +4 -0
- package/templates/default/components/AdminCard.tsx +163 -0
- package/templates/default/components/AdminEditPage.tsx +123 -0
- package/templates/default/components/AdminPrivilegeCard.tsx +184 -0
- package/templates/default/components/AdminsPage.tsx +43 -0
- package/templates/default/components/AdvancedSettingsPage.tsx +167 -0
- package/templates/default/components/AnalyticsPage.tsx +127 -0
- package/templates/default/components/BarChartBox.tsx +43 -0
- package/templates/default/components/BrowsePage.tsx +119 -0
- package/templates/default/components/CategorizedSectionPage.tsx +36 -0
- package/templates/default/components/CategoryDeleteConfirmPage.tsx +129 -0
- package/templates/default/components/CategorySectionSelectInput.tsx +139 -0
- package/templates/default/components/ConditionalFields.tsx +49 -0
- package/templates/default/components/ContainerBox.tsx +24 -0
- package/templates/default/components/DashboardPage.tsx +187 -0
- package/templates/default/components/DashboardPageAlt.tsx +43 -0
- package/templates/default/components/DefaultNavItems.tsx +3 -0
- package/templates/default/components/Dropzone.tsx +153 -0
- package/templates/default/components/EmailCard.tsx +137 -0
- package/templates/default/components/EmailPasswordForm.tsx +84 -0
- package/templates/default/components/EmailQuotaForm.tsx +72 -0
- package/templates/default/components/EmailsPage.tsx +48 -0
- package/templates/default/components/GalleryPhoto.tsx +93 -0
- package/templates/default/components/InfoCard.tsx +94 -0
- package/templates/default/components/ItemEditPage.tsx +217 -0
- package/templates/default/components/Layout.tsx +70 -0
- package/templates/default/components/LoadingSpinners.tsx +67 -0
- package/templates/default/components/LogPage.tsx +17 -0
- package/templates/default/components/Modal.tsx +99 -0
- package/templates/default/components/Navbar.tsx +29 -0
- package/templates/default/components/NavbarAlt.tsx +182 -0
- package/templates/default/components/NewAdminForm.tsx +172 -0
- package/templates/default/components/NewEmailForm.tsx +131 -0
- package/templates/default/components/NewPage.tsx +206 -0
- package/templates/default/components/NewVariantComponent.tsx +228 -0
- package/templates/default/components/PhotoGallery.tsx +35 -0
- package/templates/default/components/PieChartBox.tsx +101 -0
- package/templates/default/components/ProgressBar.tsx +24 -0
- package/templates/default/components/ProtectedDocument.tsx +78 -0
- package/templates/default/components/ProtectedImage.tsx +143 -0
- package/templates/default/components/ProtectedVideo.tsx +76 -0
- package/templates/default/components/SectionItemCard.tsx +143 -0
- package/templates/default/components/SectionItemStatusBadge.tsx +16 -0
- package/templates/default/components/SectionPage.tsx +124 -0
- package/templates/default/components/SelectBox.tsx +99 -0
- package/templates/default/components/SelectInputButtons.tsx +124 -0
- package/templates/default/components/SettingsPage.tsx +238 -0
- package/templates/default/components/Sidebar.tsx +209 -0
- package/templates/default/components/SidebarDropdownItem.tsx +74 -0
- package/templates/default/components/SidebarItem.tsx +19 -0
- package/templates/default/components/TempPage.tsx +12 -0
- package/templates/default/components/ThemeProvider.tsx +8 -0
- package/templates/default/components/TooltipComponent.tsx +27 -0
- package/templates/default/components/VariantCard.tsx +123 -0
- package/templates/default/components/VariantEditPage.tsx +229 -0
- package/templates/default/components/analytics/BounceRate.tsx +69 -0
- package/templates/default/components/analytics/LivePageViews.tsx +54 -0
- package/templates/default/components/analytics/LiveUsersCount.tsx +32 -0
- package/templates/default/components/analytics/MonthlyPageViews.tsx +41 -0
- package/templates/default/components/analytics/TopCountries.tsx +51 -0
- package/templates/default/components/analytics/TopDevices.tsx +45 -0
- package/templates/default/components/analytics/TopMediums.tsx +57 -0
- package/templates/default/components/analytics/TopSources.tsx +44 -0
- package/templates/default/components/analytics/TotalPageViews.tsx +40 -0
- package/templates/default/components/analytics/TotalSessions.tsx +40 -0
- package/templates/default/components/analytics/TotalUniqueUsers.tsx +40 -0
- package/templates/default/components/custom/RightHomeRoomVariantCard.tsx +137 -0
- package/templates/default/components/dndKit/Draggable.tsx +21 -0
- package/templates/default/components/dndKit/Droppable.tsx +20 -0
- package/templates/default/components/dndKit/SortableItem.tsx +18 -0
- package/templates/default/components/form/DateRangeFormInput.tsx +55 -0
- package/templates/default/components/form/Form.tsx +298 -0
- package/templates/default/components/form/FormInputElement.tsx +68 -0
- package/templates/default/components/form/FormInputs.tsx +108 -0
- package/templates/default/components/form/helpers/util.ts +20 -0
- package/templates/default/components/form/inputs/CheckboxFormInput.tsx +33 -0
- package/templates/default/components/form/inputs/ColorFormInput.tsx +44 -0
- package/templates/default/components/form/inputs/DateFormInput.tsx +107 -0
- package/templates/default/components/form/inputs/DocumentFormInput.tsx +124 -0
- package/templates/default/components/form/inputs/MapFormInput.tsx +139 -0
- package/templates/default/components/form/inputs/MultipleSelectFormInput.tsx +150 -0
- package/templates/default/components/form/inputs/NumberFormInput.tsx +42 -0
- package/templates/default/components/form/inputs/PasswordFormInput.tsx +47 -0
- package/templates/default/components/form/inputs/PhotoFormInput.tsx +218 -0
- package/templates/default/components/form/inputs/RichTextFormInput.tsx +133 -0
- package/templates/default/components/form/inputs/SelectFormInput.tsx +164 -0
- package/templates/default/components/form/inputs/TagsFormInput.tsx +63 -0
- package/templates/default/components/form/inputs/TextFormInput.tsx +48 -0
- package/templates/default/components/form/inputs/TextareaFormInput.tsx +47 -0
- package/templates/default/components/form/inputs/VideoFormInput.tsx +117 -0
- package/templates/default/components/pagination/Pagination.tsx +36 -0
- package/templates/default/components/pagination/PaginationButtons.tsx +145 -0
- package/templates/default/components/ui/accordion.tsx +57 -0
- package/templates/default/components/ui/alert.tsx +46 -0
- package/templates/default/components/ui/badge.tsx +33 -0
- package/templates/default/components/ui/button.tsx +57 -0
- package/templates/default/components/ui/calendar.tsx +68 -0
- package/templates/default/components/ui/card.tsx +76 -0
- package/templates/default/components/ui/checkbox.tsx +29 -0
- package/templates/default/components/ui/dropdown-menu.tsx +205 -0
- package/templates/default/components/ui/input.tsx +25 -0
- package/templates/default/components/ui/label.tsx +26 -0
- package/templates/default/components/ui/popover.tsx +31 -0
- package/templates/default/components/ui/scroll-area.tsx +42 -0
- package/templates/default/components/ui/select.tsx +164 -0
- package/templates/default/components/ui/sheet.tsx +107 -0
- package/templates/default/components/ui/switch.tsx +29 -0
- package/templates/default/components/ui/table.tsx +120 -0
- package/templates/default/components/ui/tabs.tsx +55 -0
- package/templates/default/components/ui/toast.tsx +113 -0
- package/templates/default/components/ui/toaster.tsx +35 -0
- package/templates/default/components/ui/tooltip.tsx +30 -0
- package/templates/default/components/ui/use-toast.ts +188 -0
- package/templates/default/components.json +16 -0
- package/templates/default/context/ModalProvider.tsx +53 -0
- package/templates/default/drizzle.config.ts +4 -0
- package/templates/default/dynamic-schemas/schema.ts +373 -0
- package/templates/default/env/env.js +130 -0
- package/templates/default/envConfig.ts +4 -0
- package/templates/default/hooks/useModal.ts +8 -0
- package/templates/default/lib/apiHelpers.ts +106 -0
- package/templates/default/lz.config.ts +40 -0
- package/templates/default/middleware.ts +33 -0
- package/templates/default/next.config.ts +46 -0
- package/templates/default/package.json +134 -0
- package/templates/default/postcss.config.js +6 -0
- package/templates/default/postinstall.js +14 -0
- package/templates/default/public/blank_avatar.png +0 -0
- package/templates/default/public/favicon.ico +0 -0
- package/templates/default/public/img/placeholder.svg +1 -0
- package/templates/default/public/lazemni_logo.png +0 -0
- package/templates/default/public/next.svg +1 -0
- package/templates/default/public/vercel.svg +1 -0
- package/templates/default/section-tests.ts +92 -0
- package/templates/default/styles/globals.css +88 -0
- package/templates/default/tailwind.config.js +95 -0
- package/templates/default/test.ts +77 -0
- 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,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 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,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
|
+
}
|