@delmaredigital/payload-puck 0.6.22 → 0.6.23
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/dist/api/createPuckApiRoutesVersions.js +6 -1
- package/dist/editor/PuckEditorImpl.client.js +25 -7
- package/dist/editor/components/VersionHistory.js +7 -4
- package/dist/editor/plugins/VersionHistoryPanel.js +8 -4
- package/dist/endpoints/index.d.ts +3 -0
- package/dist/endpoints/index.js +68 -14
- package/dist/plugin/hooks/isHomepageUnique.d.ts +1 -1
- package/dist/plugin/hooks/isHomepageUnique.js +10 -2
- package/dist/utils/locale.d.ts +22 -0
- package/dist/utils/locale.js +28 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/views/PuckEditorView.js +5 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { getPayload } from 'payload';
|
|
3
|
+
import { resolveLocaleFromNextRequest } from '../utils/locale.js';
|
|
3
4
|
/**
|
|
4
5
|
* Create API route handlers for /api/puck/pages/[id]/versions
|
|
5
6
|
*
|
|
@@ -70,6 +71,7 @@ import { getPayload } from 'payload';
|
|
|
70
71
|
const url = new URL(request.url);
|
|
71
72
|
const limit = parseInt(url.searchParams.get('limit') || '20', 10);
|
|
72
73
|
const page = parseInt(url.searchParams.get('page') || '1', 10);
|
|
74
|
+
const locale = resolveLocaleFromNextRequest(request);
|
|
73
75
|
// Fetch versions for this page
|
|
74
76
|
const versions = await payload.findVersions({
|
|
75
77
|
collection,
|
|
@@ -80,7 +82,10 @@ import { getPayload } from 'payload';
|
|
|
80
82
|
},
|
|
81
83
|
sort: '-updatedAt',
|
|
82
84
|
limit,
|
|
83
|
-
page
|
|
85
|
+
page,
|
|
86
|
+
...locale ? {
|
|
87
|
+
locale: locale.toString()
|
|
88
|
+
} : {}
|
|
84
89
|
});
|
|
85
90
|
return NextResponse.json({
|
|
86
91
|
docs: versions.docs,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useCallback, useMemo, useRef, createElement } from 'react';
|
|
3
|
+
import { useState, useCallback, useMemo, useRef, createElement, useEffect } from 'react';
|
|
4
4
|
import { useRouter } from 'next/navigation';
|
|
5
5
|
import { Puck } from '@puckeditor/core';
|
|
6
|
+
import { useLocale } from '@payloadcms/ui';
|
|
6
7
|
import '@puckeditor/core/puck.css';
|
|
7
8
|
import headingAnalyzer from '@puckeditor/plugin-heading-analyzer';
|
|
8
9
|
import '@puckeditor/plugin-heading-analyzer/dist/index.css';
|
|
@@ -71,6 +72,18 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
71
72
|
// Track if document was ever published (initially or during this session)
|
|
72
73
|
const [wasPublished, setWasPublished] = useState(initialStatus === 'published');
|
|
73
74
|
const { hasUnsavedChanges, markClean, markDirty } = useUnsavedChanges();
|
|
75
|
+
// Get current locale code
|
|
76
|
+
const { code: currentLocale } = useLocale();
|
|
77
|
+
// Store the initial locale on mount
|
|
78
|
+
const initialLocale = useRef(currentLocale);
|
|
79
|
+
useEffect(()=>{
|
|
80
|
+
// If the locale changes from what it was at load, force a hard refresh
|
|
81
|
+
if (initialLocale.current && currentLocale !== initialLocale.current) {
|
|
82
|
+
window.location.reload();
|
|
83
|
+
}
|
|
84
|
+
}, [
|
|
85
|
+
currentLocale
|
|
86
|
+
]);
|
|
74
87
|
// Preview modal state
|
|
75
88
|
const [isPreviewOpen, setIsPreviewOpen] = useState(false);
|
|
76
89
|
// Preview dark mode state (for toggling dark/light in preview iframe)
|
|
@@ -143,7 +156,7 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
143
156
|
// Helper to make save request with optional homepage swap
|
|
144
157
|
const makeSaveRequest = useCallback(async (data, options = {})=>{
|
|
145
158
|
const typedData = data;
|
|
146
|
-
return fetch(`${apiEndpoint}/${pageId}`, {
|
|
159
|
+
return fetch(`${apiEndpoint}/${pageId}${currentLocale ? `?locale=${currentLocale}` : ''}`, {
|
|
147
160
|
method: 'PATCH',
|
|
148
161
|
headers: {
|
|
149
162
|
'Content-Type': 'application/json'
|
|
@@ -168,7 +181,8 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
168
181
|
apiEndpoint,
|
|
169
182
|
pageId,
|
|
170
183
|
pageTitle,
|
|
171
|
-
pageSlug
|
|
184
|
+
pageSlug,
|
|
185
|
+
currentLocale
|
|
172
186
|
]);
|
|
173
187
|
// Handle homepage conflict - prompt user to swap
|
|
174
188
|
const handleHomepageConflict = useCallback(async (existingHomepage, data, publish)=>{
|
|
@@ -179,7 +193,8 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
179
193
|
// Retry with swapHomepage flag
|
|
180
194
|
const response = await makeSaveRequest(data, {
|
|
181
195
|
publish,
|
|
182
|
-
swapHomepage: true
|
|
196
|
+
swapHomepage: true,
|
|
197
|
+
currentLocale
|
|
183
198
|
});
|
|
184
199
|
if (!response.ok) {
|
|
185
200
|
const errorData = await response.json();
|
|
@@ -187,7 +202,8 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
187
202
|
}
|
|
188
203
|
return true;
|
|
189
204
|
}, [
|
|
190
|
-
makeSaveRequest
|
|
205
|
+
makeSaveRequest,
|
|
206
|
+
currentLocale
|
|
191
207
|
]);
|
|
192
208
|
// Handle save (as draft)
|
|
193
209
|
const handleSave = useCallback(async (data)=>{
|
|
@@ -195,7 +211,8 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
195
211
|
const typedData = data;
|
|
196
212
|
try {
|
|
197
213
|
const response = await makeSaveRequest(data, {
|
|
198
|
-
publish: false
|
|
214
|
+
publish: false,
|
|
215
|
+
currentLocale
|
|
199
216
|
});
|
|
200
217
|
if (!response.ok) {
|
|
201
218
|
const errorData = await response.json();
|
|
@@ -234,7 +251,8 @@ import { useAiPrompts } from '../ai/hooks/useAiPrompts.js';
|
|
|
234
251
|
handleHomepageConflict,
|
|
235
252
|
markClean,
|
|
236
253
|
onSaveSuccess,
|
|
237
|
-
onSaveError
|
|
254
|
+
onSaveError,
|
|
255
|
+
currentLocale
|
|
238
256
|
]);
|
|
239
257
|
// Handle publish
|
|
240
258
|
const handlePublish = useCallback(async (data)=>{
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback, useEffect, useRef, memo } from 'react';
|
|
4
|
+
import { useLocale } from '@payloadcms/ui';
|
|
4
5
|
import { History, Loader2, Check, RotateCcw, X, ChevronDown } from 'lucide-react';
|
|
5
6
|
// Shared styles
|
|
6
7
|
const styles = {
|
|
@@ -188,11 +189,12 @@ const styles = {
|
|
|
188
189
|
const [isAvailable, setIsAvailable] = useState(null);
|
|
189
190
|
const [hoveredIndex, setHoveredIndex] = useState(null);
|
|
190
191
|
const dropdownRef = useRef(null);
|
|
192
|
+
const { code: currentLocale } = useLocale();
|
|
191
193
|
// Check if versions endpoint is available on mount
|
|
192
194
|
useEffect(()=>{
|
|
193
195
|
async function checkAvailability() {
|
|
194
196
|
try {
|
|
195
|
-
const response = await fetch(`${apiEndpoint}/${pageId}/versions?limit=1`, {
|
|
197
|
+
const response = await fetch(`${apiEndpoint}/${pageId}/versions?limit=1${currentLocale ? `&locale=${currentLocale}` : ''}`, {
|
|
196
198
|
method: 'GET'
|
|
197
199
|
});
|
|
198
200
|
setIsAvailable(response.status !== 404);
|
|
@@ -220,7 +222,7 @@ const styles = {
|
|
|
220
222
|
setIsLoading(true);
|
|
221
223
|
setError(null);
|
|
222
224
|
try {
|
|
223
|
-
const response = await fetch(`${apiEndpoint}/${pageId}/versions?limit=20`);
|
|
225
|
+
const response = await fetch(`${apiEndpoint}/${pageId}/versions?limit=20${currentLocale ? `&locale=${currentLocale}` : ''}`);
|
|
224
226
|
if (!response.ok) {
|
|
225
227
|
throw new Error('Failed to fetch versions');
|
|
226
228
|
}
|
|
@@ -252,13 +254,14 @@ const styles = {
|
|
|
252
254
|
}
|
|
253
255
|
setIsRestoring(true);
|
|
254
256
|
try {
|
|
255
|
-
const response = await fetch(`${apiEndpoint}/${pageId}/
|
|
257
|
+
const response = await fetch(`${apiEndpoint}/${pageId}/restore`, {
|
|
256
258
|
method: 'POST',
|
|
257
259
|
headers: {
|
|
258
260
|
'Content-Type': 'application/json'
|
|
259
261
|
},
|
|
260
262
|
body: JSON.stringify({
|
|
261
|
-
versionId: version.id
|
|
263
|
+
versionId: version.id,
|
|
264
|
+
locale: currentLocale
|
|
262
265
|
})
|
|
263
266
|
});
|
|
264
267
|
if (!response.ok) {
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState, useCallback, useEffect, memo } from 'react';
|
|
4
4
|
import { createUsePuck } from '@puckeditor/core';
|
|
5
5
|
import { Loader2, Check, RotateCcw, AlertCircle } from 'lucide-react';
|
|
6
|
+
import { useLocale } from '@payloadcms/ui';
|
|
6
7
|
// Create usePuck hook for accessing editor state and dispatch
|
|
7
8
|
const usePuck = createUsePuck();
|
|
8
9
|
// Panel styles using Puck's CSS variables
|
|
@@ -186,12 +187,13 @@ const styles = {
|
|
|
186
187
|
const [error, setError] = useState(null);
|
|
187
188
|
const [hoveredIndex, setHoveredIndex] = useState(null);
|
|
188
189
|
const [successMessage, setSuccessMessage] = useState(null);
|
|
190
|
+
const { code: currentLocale } = useLocale();
|
|
189
191
|
// Fetch versions on mount
|
|
190
192
|
const fetchVersions = useCallback(async ()=>{
|
|
191
193
|
setIsLoading(true);
|
|
192
194
|
setError(null);
|
|
193
195
|
try {
|
|
194
|
-
const url = `${apiEndpoint}/${pageId}/versions?limit=20`;
|
|
196
|
+
const url = `${apiEndpoint}/${pageId}/versions?limit=20${currentLocale ? `&locale=${currentLocale}` : ''}`;
|
|
195
197
|
const response = await fetch(url);
|
|
196
198
|
if (!response.ok) {
|
|
197
199
|
if (response.status === 404) {
|
|
@@ -229,13 +231,14 @@ const styles = {
|
|
|
229
231
|
setSuccessMessage(null);
|
|
230
232
|
try {
|
|
231
233
|
// Call restore endpoint
|
|
232
|
-
const response = await fetch(`${apiEndpoint}/${pageId}/
|
|
234
|
+
const response = await fetch(`${apiEndpoint}/${pageId}/restore`, {
|
|
233
235
|
method: 'POST',
|
|
234
236
|
headers: {
|
|
235
237
|
'Content-Type': 'application/json'
|
|
236
238
|
},
|
|
237
239
|
body: JSON.stringify({
|
|
238
|
-
versionId: version.id
|
|
240
|
+
versionId: version.id,
|
|
241
|
+
locale: currentLocale
|
|
239
242
|
})
|
|
240
243
|
});
|
|
241
244
|
if (!response.ok) {
|
|
@@ -268,7 +271,8 @@ const styles = {
|
|
|
268
271
|
pageId,
|
|
269
272
|
dispatch,
|
|
270
273
|
onRestoreSuccess,
|
|
271
|
-
fetchVersions
|
|
274
|
+
fetchVersions,
|
|
275
|
+
currentLocale
|
|
272
276
|
]);
|
|
273
277
|
// Format date for display
|
|
274
278
|
function formatDate(dateStr) {
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These handlers are registered via config.endpoints in the plugin.
|
|
5
5
|
* They provide CRUD operations for Puck-enabled collections.
|
|
6
|
+
*
|
|
7
|
+
* Access control: All handlers pass `overrideAccess: false` and `req` to
|
|
8
|
+
* Payload's local API, so collection-level access rules are enforced.
|
|
6
9
|
*/
|
|
7
10
|
import type { PayloadHandler } from 'payload';
|
|
8
11
|
export interface PuckEndpointOptions {
|
package/dist/endpoints/index.js
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These handlers are registered via config.endpoints in the plugin.
|
|
5
5
|
* They provide CRUD operations for Puck-enabled collections.
|
|
6
|
+
*
|
|
7
|
+
* Access control: All handlers pass `overrideAccess: false` and `req` to
|
|
8
|
+
* Payload's local API, so collection-level access rules are enforced.
|
|
6
9
|
*/ import { APIError } from 'payload';
|
|
7
10
|
import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepageUnique.js';
|
|
11
|
+
import { resolveLocale } from '../utils/locale.js';
|
|
8
12
|
/**
|
|
9
13
|
* GET /api/puck/:collection
|
|
10
14
|
* List all documents in a Puck-enabled collection
|
|
@@ -20,11 +24,17 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
20
24
|
status: 400
|
|
21
25
|
});
|
|
22
26
|
}
|
|
27
|
+
const locale = resolveLocale(req);
|
|
23
28
|
const result = await req.payload.find({
|
|
24
29
|
collection: collection,
|
|
30
|
+
req,
|
|
31
|
+
overrideAccess: false,
|
|
25
32
|
draft: true,
|
|
26
33
|
depth: 0,
|
|
27
|
-
limit: 100
|
|
34
|
+
limit: 100,
|
|
35
|
+
...locale ? {
|
|
36
|
+
locale
|
|
37
|
+
} : {}
|
|
28
38
|
});
|
|
29
39
|
return Response.json(result);
|
|
30
40
|
} catch (error) {
|
|
@@ -53,10 +63,17 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
53
63
|
});
|
|
54
64
|
}
|
|
55
65
|
const body = await req.json?.();
|
|
66
|
+
const { _locale, ...data } = body || {};
|
|
67
|
+
const locale = resolveLocale(req, _locale);
|
|
56
68
|
const doc = await req.payload.create({
|
|
57
69
|
collection: collection,
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
req,
|
|
71
|
+
overrideAccess: false,
|
|
72
|
+
data,
|
|
73
|
+
draft: true,
|
|
74
|
+
...locale ? {
|
|
75
|
+
locale
|
|
76
|
+
} : {}
|
|
60
77
|
});
|
|
61
78
|
return Response.json({
|
|
62
79
|
doc
|
|
@@ -87,11 +104,17 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
87
104
|
status: 400
|
|
88
105
|
});
|
|
89
106
|
}
|
|
107
|
+
const locale = resolveLocale(req);
|
|
90
108
|
const doc = await req.payload.findByID({
|
|
91
109
|
collection: collection,
|
|
110
|
+
req,
|
|
111
|
+
overrideAccess: false,
|
|
92
112
|
id,
|
|
93
113
|
draft: true,
|
|
94
|
-
depth: 0
|
|
114
|
+
depth: 0,
|
|
115
|
+
...locale ? {
|
|
116
|
+
locale
|
|
117
|
+
} : {}
|
|
95
118
|
});
|
|
96
119
|
return Response.json({
|
|
97
120
|
doc
|
|
@@ -123,7 +146,8 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
123
146
|
});
|
|
124
147
|
}
|
|
125
148
|
const body = await req.json?.();
|
|
126
|
-
const { _status, swapHomepage, ...data } = body || {};
|
|
149
|
+
const { _status, _locale, swapHomepage, ...data } = body || {};
|
|
150
|
+
const locale = resolveLocale(req, _locale);
|
|
127
151
|
// Determine if this is a publish or draft save
|
|
128
152
|
const shouldPublish = _status === 'published';
|
|
129
153
|
// Handle homepage swap if requested
|
|
@@ -133,6 +157,8 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
133
157
|
// Find the current homepage
|
|
134
158
|
const existingHomepage = await req.payload.find({
|
|
135
159
|
collection: collection,
|
|
160
|
+
req,
|
|
161
|
+
overrideAccess: false,
|
|
136
162
|
where: {
|
|
137
163
|
and: [
|
|
138
164
|
{
|
|
@@ -148,26 +174,40 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
148
174
|
]
|
|
149
175
|
},
|
|
150
176
|
limit: 1,
|
|
151
|
-
depth: 0
|
|
177
|
+
depth: 0,
|
|
178
|
+
...locale ? {
|
|
179
|
+
locale
|
|
180
|
+
} : {}
|
|
152
181
|
});
|
|
153
182
|
// Unset the existing homepage if found
|
|
154
183
|
if (existingHomepage.docs.length > 0) {
|
|
155
184
|
const existingId = String(existingHomepage.docs[0].id);
|
|
156
|
-
await unsetHomepage(req.payload, collection, existingId);
|
|
185
|
+
await unsetHomepage(req.payload, collection, existingId, locale);
|
|
157
186
|
}
|
|
158
187
|
}
|
|
159
188
|
const doc = await req.payload.update({
|
|
160
189
|
collection: collection,
|
|
190
|
+
req,
|
|
191
|
+
overrideAccess: false,
|
|
161
192
|
id,
|
|
162
193
|
data: {
|
|
163
194
|
...data,
|
|
164
195
|
_status: shouldPublish ? 'published' : 'draft'
|
|
165
196
|
},
|
|
166
197
|
draft: !shouldPublish,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
198
|
+
context: {
|
|
199
|
+
// Skip the isHomepage hook if we've already handled the swap
|
|
200
|
+
...swapHomepage && {
|
|
201
|
+
skipIsHomepageHook: true
|
|
202
|
+
},
|
|
203
|
+
// Pass locale to context so hooks can access it without re-reading body
|
|
204
|
+
...locale && {
|
|
205
|
+
locale
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
...locale ? {
|
|
209
|
+
locale
|
|
210
|
+
} : {}
|
|
171
211
|
});
|
|
172
212
|
return Response.json({
|
|
173
213
|
doc,
|
|
@@ -221,6 +261,8 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
221
261
|
}
|
|
222
262
|
await req.payload.delete({
|
|
223
263
|
collection: collection,
|
|
264
|
+
req,
|
|
265
|
+
overrideAccess: false,
|
|
224
266
|
id
|
|
225
267
|
});
|
|
226
268
|
return Response.json({
|
|
@@ -245,6 +287,7 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
245
287
|
try {
|
|
246
288
|
const collection = req.routeParams?.collection;
|
|
247
289
|
const id = req.routeParams?.id;
|
|
290
|
+
const locale = resolveLocale(req);
|
|
248
291
|
if (!collections.includes(collection)) {
|
|
249
292
|
return Response.json({
|
|
250
293
|
error: `Collection '${collection}' is not configured for Puck`
|
|
@@ -254,13 +297,19 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
254
297
|
}
|
|
255
298
|
const versions = await req.payload.findVersions({
|
|
256
299
|
collection: collection,
|
|
300
|
+
req,
|
|
301
|
+
overrideAccess: false,
|
|
257
302
|
where: {
|
|
258
303
|
parent: {
|
|
259
304
|
equals: id
|
|
260
305
|
}
|
|
261
306
|
},
|
|
262
307
|
sort: '-updatedAt',
|
|
263
|
-
limit: 20
|
|
308
|
+
limit: 20,
|
|
309
|
+
...locale ? {
|
|
310
|
+
locale,
|
|
311
|
+
fallbackLocale: false
|
|
312
|
+
} : {}
|
|
264
313
|
});
|
|
265
314
|
return Response.json({
|
|
266
315
|
versions: versions.docs
|
|
@@ -292,7 +341,7 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
292
341
|
});
|
|
293
342
|
}
|
|
294
343
|
const body = await req.json?.();
|
|
295
|
-
const { versionId } = body || {};
|
|
344
|
+
const { versionId, locale } = body || {};
|
|
296
345
|
if (!versionId) {
|
|
297
346
|
return Response.json({
|
|
298
347
|
error: 'Missing versionId in request body'
|
|
@@ -302,7 +351,12 @@ import { unsetHomepage, HomepageConflictError } from '../plugin/hooks/isHomepage
|
|
|
302
351
|
}
|
|
303
352
|
const doc = await req.payload.restoreVersion({
|
|
304
353
|
collection: collection,
|
|
305
|
-
|
|
354
|
+
req,
|
|
355
|
+
overrideAccess: false,
|
|
356
|
+
id: versionId,
|
|
357
|
+
...locale ? {
|
|
358
|
+
locale: locale.toString()
|
|
359
|
+
} : {}
|
|
306
360
|
});
|
|
307
361
|
return Response.json({
|
|
308
362
|
doc
|
|
@@ -52,4 +52,4 @@ export declare function createIsHomepageUniqueHook(options?: IsHomepageUniqueHoo
|
|
|
52
52
|
* Unsets isHomepage on the specified page.
|
|
53
53
|
* Used when swapping homepages.
|
|
54
54
|
*/
|
|
55
|
-
export declare function unsetHomepage(payload: any, collectionSlug: string, pageId: string): Promise<void>;
|
|
55
|
+
export declare function unsetHomepage(payload: any, collectionSlug: string, pageId: string, locale?: string): Promise<void>;
|
|
@@ -48,9 +48,14 @@ import { APIError } from 'payload';
|
|
|
48
48
|
return data;
|
|
49
49
|
}
|
|
50
50
|
const collectionSlug = options.collectionSlug || collection.slug;
|
|
51
|
+
// Use locale from context (passed by endpoint handler) or fall back to req.locale
|
|
52
|
+
const locale = context?.locale || req.locale;
|
|
51
53
|
// Query for existing homepage (excluding current document)
|
|
52
54
|
const existingHomepage = await req.payload.find({
|
|
53
55
|
collection: collectionSlug,
|
|
56
|
+
...locale ? {
|
|
57
|
+
locale: locale.toString()
|
|
58
|
+
} : {},
|
|
54
59
|
where: {
|
|
55
60
|
and: [
|
|
56
61
|
{
|
|
@@ -85,7 +90,7 @@ import { APIError } from 'payload';
|
|
|
85
90
|
/**
|
|
86
91
|
* Unsets isHomepage on the specified page.
|
|
87
92
|
* Used when swapping homepages.
|
|
88
|
-
*/ export async function unsetHomepage(payload, collectionSlug, pageId) {
|
|
93
|
+
*/ export async function unsetHomepage(payload, collectionSlug, pageId, locale) {
|
|
89
94
|
await payload.update({
|
|
90
95
|
collection: collectionSlug,
|
|
91
96
|
id: pageId,
|
|
@@ -95,6 +100,9 @@ import { APIError } from 'payload';
|
|
|
95
100
|
// Skip hooks to avoid infinite loops
|
|
96
101
|
context: {
|
|
97
102
|
skipIsHomepageHook: true
|
|
98
|
-
}
|
|
103
|
+
},
|
|
104
|
+
...locale ? {
|
|
105
|
+
locale: locale.toString()
|
|
106
|
+
} : {}
|
|
99
107
|
});
|
|
100
108
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale Resolver — Determines the locale for a Payload operation.
|
|
3
|
+
*/
|
|
4
|
+
import type { PayloadHandler } from 'payload';
|
|
5
|
+
import type { NextRequest } from 'next/server';
|
|
6
|
+
/**
|
|
7
|
+
* Resolves the locale to use for a Payload operation.
|
|
8
|
+
*
|
|
9
|
+
* Priority:
|
|
10
|
+
* 1. Explicit `bodyLocale` (from `_locale` in the request body, sent by PuckEditor)
|
|
11
|
+
* 2. `?locale=` query param (standard REST convention, already parsed by Payload)
|
|
12
|
+
* 3. `req.locale` set by Payload's middleware (from admin UI context)
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveLocale(req: Parameters<PayloadHandler>[0], bodyLocale?: string): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Resolves the locale from a Next.js API route request.
|
|
17
|
+
*
|
|
18
|
+
* Priority:
|
|
19
|
+
* 1. Explicit `bodyLocale` (from `_locale` in the request body)
|
|
20
|
+
* 2. `?locale=` query param
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveLocaleFromNextRequest(req: NextRequest, bodyLocale?: string): string | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale Resolver — Determines the locale for a Payload operation.
|
|
3
|
+
*/ /**
|
|
4
|
+
* Resolves the locale to use for a Payload operation.
|
|
5
|
+
*
|
|
6
|
+
* Priority:
|
|
7
|
+
* 1. Explicit `bodyLocale` (from `_locale` in the request body, sent by PuckEditor)
|
|
8
|
+
* 2. `?locale=` query param (standard REST convention, already parsed by Payload)
|
|
9
|
+
* 3. `req.locale` set by Payload's middleware (from admin UI context)
|
|
10
|
+
*/ export function resolveLocale(req, bodyLocale) {
|
|
11
|
+
if (bodyLocale) return bodyLocale;
|
|
12
|
+
const queryLocale = req.query?.locale;
|
|
13
|
+
if (queryLocale) return queryLocale;
|
|
14
|
+
if (req.locale) return typeof req.locale === 'string' ? req.locale : req.locale.code;
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the locale from a Next.js API route request.
|
|
19
|
+
*
|
|
20
|
+
* Priority:
|
|
21
|
+
* 1. Explicit `bodyLocale` (from `_locale` in the request body)
|
|
22
|
+
* 2. `?locale=` query param
|
|
23
|
+
*/ export function resolveLocaleFromNextRequest(req, bodyLocale) {
|
|
24
|
+
if (bodyLocale) return bodyLocale;
|
|
25
|
+
const queryLocale = req.nextUrl.searchParams.get('locale') ?? undefined;
|
|
26
|
+
if (queryLocale) return queryLocale;
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.6.
|
|
1
|
+
export declare const VERSION = "0.6.23";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/generate-version.js - do not edit manually
|
|
2
|
-
export const VERSION = '0.6.
|
|
2
|
+
export const VERSION = '0.6.23';
|
|
@@ -68,12 +68,16 @@ import { mapPayloadFieldsToRootProps } from '../api/utils/mapRootProps.js';
|
|
|
68
68
|
let page = null;
|
|
69
69
|
let error = null;
|
|
70
70
|
const needsRelationships = typeof previewUrlConfig === 'function';
|
|
71
|
+
// Read locale from searchParams (e.g. ?locale=bg)
|
|
72
|
+
const resolvedSearch = await searchParams;
|
|
73
|
+
const locale = resolvedSearch?.locale || req.locale;
|
|
71
74
|
try {
|
|
72
75
|
page = await payload.findByID({
|
|
73
76
|
collection: collection,
|
|
74
77
|
id: pageId,
|
|
75
78
|
draft: true,
|
|
76
|
-
depth: needsRelationships ? 1 : 0
|
|
79
|
+
depth: needsRelationships ? 1 : 0,
|
|
80
|
+
locale
|
|
77
81
|
});
|
|
78
82
|
} catch (err) {
|
|
79
83
|
console.error('[PuckEditorView] Error fetching page:', err);
|