create-nextblock 0.2.46 → 0.2.47
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/nextblock-template/app/cms/dashboard/actions.ts +98 -0
- package/templates/nextblock-template/app/cms/dashboard/page.tsx +76 -153
- package/templates/nextblock-template/app/cms/media/components/MediaEditForm.tsx +16 -11
- package/templates/nextblock-template/app/cms/media/components/MediaUploadForm.tsx +23 -12
- package/templates/nextblock-template/app/cms/navigation/components/DeleteNavItemButton.tsx +4 -0
- package/templates/nextblock-template/app/cms/navigation/components/NavigationItemForm.tsx +30 -6
- package/templates/nextblock-template/app/cms/pages/components/PageForm.tsx +17 -11
- package/templates/nextblock-template/app/cms/pages/page.tsx +6 -3
- package/templates/nextblock-template/app/cms/posts/components/PostForm.tsx +18 -12
- package/templates/nextblock-template/app/cms/posts/page.tsx +8 -5
- package/templates/nextblock-template/app/cms/revisions/RevisionHistoryButton.tsx +18 -5
- package/templates/nextblock-template/app/cms/settings/copyright/components/CopyrightForm.tsx +20 -4
- package/templates/nextblock-template/app/cms/settings/extra-translations/page.tsx +33 -7
- package/templates/nextblock-template/app/cms/settings/languages/components/DeleteLanguageButton.tsx +3 -3
- package/templates/nextblock-template/app/cms/settings/languages/components/LanguageForm.tsx +41 -13
- package/templates/nextblock-template/app/cms/settings/languages/page.tsx +15 -13
- package/templates/nextblock-template/app/cms/settings/logos/actions.ts +2 -3
- package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +50 -0
- package/templates/nextblock-template/app/cms/settings/logos/components/LogoForm.tsx +14 -2
- package/templates/nextblock-template/app/cms/settings/logos/page.tsx +3 -6
- package/templates/nextblock-template/app/cms/users/components/UserForm.tsx +33 -13
- package/templates/nextblock-template/hooks/use-hotkeys.ts +27 -0
- package/templates/nextblock-template/next-env.d.ts +1 -1
- package/templates/nextblock-template/package.json +1 -1
|
@@ -17,8 +17,9 @@ import {
|
|
|
17
17
|
DropdownMenuTrigger,
|
|
18
18
|
DropdownMenuSeparator,
|
|
19
19
|
} from '@nextblock-cms/ui'
|
|
20
|
-
import {
|
|
20
|
+
import { getLogos } from './actions'
|
|
21
21
|
import MediaImage from '@/app/cms/media/components/MediaImage'
|
|
22
|
+
import DeleteLogoButton from './components/DeleteLogoButton'
|
|
22
23
|
|
|
23
24
|
const R2_BASE_URL = process.env.NEXT_PUBLIC_R2_BASE_URL || ''
|
|
24
25
|
|
|
@@ -99,11 +100,7 @@ export default async function CmsLogosListPage() {
|
|
|
99
100
|
</Link>
|
|
100
101
|
</DropdownMenuItem>
|
|
101
102
|
<DropdownMenuSeparator />
|
|
102
|
-
<
|
|
103
|
-
<button type="submit" className="w-full text-left px-2 py-1.5 text-sm text-red-500">
|
|
104
|
-
Delete
|
|
105
|
-
</button>
|
|
106
|
-
</form>
|
|
103
|
+
<DeleteLogoButton logoId={logo.id} />
|
|
107
104
|
</DropdownMenuContent>
|
|
108
105
|
</DropdownMenu>
|
|
109
106
|
</TableCell>
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// app/cms/users/components/UserForm.tsx
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
|
-
import { useEffect, useState, useTransition } from "react";
|
|
4
|
+
import { useEffect, useState, useTransition, useRef } from "react";
|
|
5
|
+
import { useHotkeys } from "@/hooks/use-hotkeys";
|
|
5
6
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
6
7
|
import { Button } from "@nextblock-cms/ui";
|
|
8
|
+
import { Spinner, Alert, AlertDescription, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@nextblock-cms/ui";
|
|
9
|
+
import { Info } from "lucide-react";
|
|
7
10
|
import { Input } from "@nextblock-cms/ui";
|
|
8
11
|
import { Label } from "@nextblock-cms/ui";
|
|
9
12
|
import {
|
|
@@ -85,18 +88,15 @@ export default function UserForm({
|
|
|
85
88
|
|
|
86
89
|
const userRoles: UserRole[] = ['USER', 'WRITER', 'ADMIN'];
|
|
87
90
|
|
|
91
|
+
const formRef = useRef<HTMLFormElement>(null);
|
|
92
|
+
useHotkeys('ctrl+s', () => formRef.current?.requestSubmit());
|
|
93
|
+
|
|
88
94
|
return (
|
|
89
|
-
<form onSubmit={handleSubmit} className="space-y-6">
|
|
95
|
+
<form ref={formRef} onSubmit={handleSubmit} className="space-y-6">
|
|
90
96
|
{formMessage && (
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
? 'bg-green-100 text-green-700 border border-green-200'
|
|
95
|
-
: 'bg-red-100 text-red-700 border border-red-200'
|
|
96
|
-
}`}
|
|
97
|
-
>
|
|
98
|
-
{formMessage.text}
|
|
99
|
-
</div>
|
|
97
|
+
<Alert variant={formMessage.type === 'success' ? 'success' : 'destructive'}>
|
|
98
|
+
<AlertDescription>{formMessage.text}</AlertDescription>
|
|
99
|
+
</Alert>
|
|
100
100
|
)}
|
|
101
101
|
<div>
|
|
102
102
|
<Label htmlFor="email">Email (Read-only)</Label>
|
|
@@ -114,7 +114,21 @@ export default function UserForm({
|
|
|
114
114
|
</div>
|
|
115
115
|
|
|
116
116
|
<div>
|
|
117
|
-
<
|
|
117
|
+
<div className="flex items-center gap-2 mb-2">
|
|
118
|
+
<Label htmlFor="role">Role</Label>
|
|
119
|
+
<TooltipProvider>
|
|
120
|
+
<Tooltip>
|
|
121
|
+
<TooltipTrigger asChild>
|
|
122
|
+
<Info className="h-4 w-4 text-muted-foreground opacity-70 cursor-pointer" />
|
|
123
|
+
</TooltipTrigger>
|
|
124
|
+
<TooltipContent className="max-w-xs">
|
|
125
|
+
<p><strong>ADMIN:</strong> Full access to settings and content.</p>
|
|
126
|
+
<p><strong>WRITER:</strong> Can create/edit content, no settings access.</p>
|
|
127
|
+
<p><strong>USER:</strong> Read-only access.</p>
|
|
128
|
+
</TooltipContent>
|
|
129
|
+
</Tooltip>
|
|
130
|
+
</TooltipProvider>
|
|
131
|
+
</div>
|
|
118
132
|
<Select name="role" value={role} onValueChange={(value) => setRole(value as UserRole)} required>
|
|
119
133
|
<SelectTrigger className="mt-1"><SelectValue placeholder="Select role" /></SelectTrigger>
|
|
120
134
|
<SelectContent>
|
|
@@ -130,7 +144,13 @@ export default function UserForm({
|
|
|
130
144
|
Cancel
|
|
131
145
|
</Button>
|
|
132
146
|
<Button type="submit" disabled={isPending || authLoading}>
|
|
133
|
-
{isPending ?
|
|
147
|
+
{isPending ? (
|
|
148
|
+
<>
|
|
149
|
+
<Spinner className="mr-2 h-4 w-4" /> Saving...
|
|
150
|
+
</>
|
|
151
|
+
) : (
|
|
152
|
+
actionButtonText
|
|
153
|
+
)}
|
|
134
154
|
</Button>
|
|
135
155
|
</div>
|
|
136
156
|
</form>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook to handle keyboard shortcuts.
|
|
5
|
+
* Currently optimized for 'ctrl+s' / 'meta+s'.
|
|
6
|
+
*
|
|
7
|
+
* @param key The key combination to listen for (e.g. 'ctrl+s')
|
|
8
|
+
* @param callback The function to call when the key combination is pressed
|
|
9
|
+
* @param deps Dependencies array for the effect
|
|
10
|
+
*/
|
|
11
|
+
export function useHotkeys(key: string, callback: (event: KeyboardEvent) => void, deps: any[] = []) {
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
14
|
+
const isCtrl = event.ctrlKey || event.metaKey; // cmd on mac, ctrl on windows
|
|
15
|
+
const keyLower = event.key.toLowerCase();
|
|
16
|
+
|
|
17
|
+
// Check for ctrl+s / cmd+s
|
|
18
|
+
if ((key === 'ctrl+s' || key === 'meta+s') && isCtrl && keyLower === 's') {
|
|
19
|
+
event.preventDefault();
|
|
20
|
+
callback(event);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
window.addEventListener('keydown', handleKeyDown);
|
|
25
|
+
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
26
|
+
}, [key, ...deps]); // callback should be stable or included in deps if handled by caller
|
|
27
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/
|
|
3
|
+
import "./.next/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|