Compare commits
19 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96d99cb361 | ||
|
|
3f375cc6ee | ||
|
|
3847428f0a | ||
|
|
7b6a760e97 | ||
|
|
0c1004537d | ||
|
|
e765a5e866 | ||
|
|
f543e8963e | ||
|
|
163f3c0692 | ||
|
|
4241811fa9 | ||
|
|
8110cb9956 | ||
|
|
e5ca476d7f | ||
|
|
161749bde9 | ||
|
|
22f120dc85 | ||
|
|
e7b44dc545 | ||
|
|
8b44676b0d | ||
|
|
613d3b090e | ||
|
|
fb603448d8 | ||
|
|
f50174f5b8 | ||
|
|
17e0547db3 |
@@ -6,8 +6,8 @@ desc: The Join field provides the ability to work on related documents. Learn ho
|
||||
keywords: join, relationship, junction, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The Join Field is used to make Relationship fields in the opposite direction. It is used to show the relationship from
|
||||
the other side. The field itself acts as a virtual field, in that no new data is stored on the collection with a Join
|
||||
The Join Field is used to make Relationship and Upload fields available in the opposite direction. With a Join you can edit and view collections
|
||||
having reference to a specific collection document. The field itself acts as a virtual field, in that no new data is stored on the collection with a Join
|
||||
field. Instead, the Admin UI surfaces the related documents for a better editing experience and is surfaced by Payload's
|
||||
APIs.
|
||||
|
||||
@@ -16,6 +16,7 @@ The Join field is useful in scenarios including:
|
||||
- To surface `Order`s for a given `Product`
|
||||
- To view and edit `Posts` belonging to a `Category`
|
||||
- To work with any bi-directional relationship data
|
||||
- Displaying where a document or upload is used in other documents
|
||||
|
||||
<LightDarkImage
|
||||
srcLight="https://payloadcms.com/images/docs/fields/join.png"
|
||||
@@ -24,8 +25,8 @@ The Join field is useful in scenarios including:
|
||||
caption="Admin Panel screenshot of Join field"
|
||||
/>
|
||||
|
||||
For the Join field to work, you must have an existing [relationship](./relationship) field in the collection you are
|
||||
joining. This will reference the collection and path of the field of the related documents.
|
||||
For the Join field to work, you must have an existing [relationship](./relationship) or [upload](./upload) field in the
|
||||
collection you are joining. This will reference the collection and path of the field of the related documents.
|
||||
To add a Relationship Field, set the `type` to `join` in your [Field Config](./overview):
|
||||
|
||||
```ts
|
||||
@@ -122,7 +123,7 @@ complete control over any type of relational architecture in Payload, all wrappe
|
||||
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`name`** \* | To be used as the property name when retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`collection`** \* | The `slug`s having the relationship field. |
|
||||
| **`on`** \* | The relationship field name of the field that relates to collection document. Use dot notation for nested paths, like 'myGroup.relationName'. |
|
||||
| **`on`** \* | The name of the relationship or upload field that relates to the collection document. Use dot notation for nested paths, like 'myGroup.relationName'. |
|
||||
| **`maxDepth`** | Default is 1, Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/getting-started/concepts#field-level-max-depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
|
||||
@@ -90,6 +90,7 @@ The Relationship Field inherits all of the default options from the base [Field
|
||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`isSortable`** | Set to `true` if you'd like this field to be sortable within the Admin UI using drag and drop (only works when `hasMany` is set to `true`). |
|
||||
| **`allowCreate`** | Set to `false` if you'd like to disable the ability to create new documents from within the relationship field. |
|
||||
| **`allowEdit`** | Set to `false` if you'd like to disable the ability to edit documents from within the relationship field. |
|
||||
| **`sortOptions`** | Define a default sorting order for the options within a Relationship field's dropdown. [More](#sortOptions) |
|
||||
|
||||
### Sort Options
|
||||
|
||||
@@ -6,7 +6,8 @@ desc: Upload fields will allow a file to be uploaded, only from a collection sup
|
||||
keywords: upload, images media, fields, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, nextjs
|
||||
---
|
||||
|
||||
The Upload Field allows for the selection of a Document from a Collection supporting [Uploads](../upload/overview), and formats the selection as a thumbnail in the Admin Panel.
|
||||
The Upload Field allows for the selection of a Document from a Collection supporting [Uploads](../upload/overview), and
|
||||
formats the selection as a thumbnail in the Admin Panel.
|
||||
|
||||
Upload fields are useful for a variety of use cases, such as:
|
||||
|
||||
@@ -15,10 +16,10 @@ Upload fields are useful for a variety of use cases, such as:
|
||||
- To give a layout building block the ability to feature a background image
|
||||
|
||||
<LightDarkImage
|
||||
srcLight="https://payloadcms.com/images/docs/fields/upload.png"
|
||||
srcDark="https://payloadcms.com/images/docs/fields/upload-dark.png"
|
||||
alt="Shows an upload field in the Payload Admin Panel"
|
||||
caption="Admin Panel screenshot of an Upload field"
|
||||
srcLight="https://payloadcms.com/images/docs/fields/upload.png"
|
||||
srcDark="https://payloadcms.com/images/docs/fields/upload-dark.png"
|
||||
alt="Shows an upload field in the Payload Admin Panel"
|
||||
caption="Admin Panel screenshot of an Upload field"
|
||||
/>
|
||||
|
||||
To create an Upload Field, set the `type` to `upload` in your [Field Config](./overview):
|
||||
@@ -43,7 +44,7 @@ export const MyUploadField: Field = {
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`*relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. <strong>Note: the related collection must be configured to support Uploads.</strong> |
|
||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
|
||||
@@ -97,7 +98,7 @@ prevent all, or a `Where` query. When using a function, it will be
|
||||
called with an argument object with the following properties:
|
||||
|
||||
| Property | Description |
|
||||
| ------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
|---------------|-------------------------------------------------------------------------------------------------------|
|
||||
| `relationTo` | The collection `slug` to filter against, limited to this field's `relationTo` property |
|
||||
| `data` | An object containing the full collection or global document currently being edited |
|
||||
| `siblingData` | An object containing document data that is scoped to only fields within the same parent of this field |
|
||||
@@ -127,3 +128,10 @@ You can learn more about writing queries [here](/docs/queries/overview).
|
||||
unless you call the default upload field validation function imported from{' '}
|
||||
<strong>payload/shared</strong> in your validate function.
|
||||
</Banner>
|
||||
|
||||
## Bi-directional relationships
|
||||
|
||||
The `upload` field on its own is used to reference documents in an upload collection. This can be considered a "one-way"
|
||||
relationship. If you wish to allow an editor to visit the upload document and see where it is being used, you may use
|
||||
the `join` field in the upload enabled collection. Read more about bi-directional relationships using
|
||||
the [Join field](./join)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload-monorepo",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -99,7 +99,7 @@
|
||||
"prettier --write",
|
||||
"eslint --cache --fix"
|
||||
],
|
||||
"templates/website/**/*": "sh -c \"cd templates/website; pnpm install --ignore-workspace; pnpm run lint --fix\"",
|
||||
"templates/website/**/*": "sh -c \"cd templates/website; pnpm install --no-frozen-lockfile --ignore-workspace; pnpm run lint --fix\"",
|
||||
"tsconfig.json": "node scripts/reset-tsconfig.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-payload-app",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The officially supported MongoDB database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import ObjectIdImport from 'bson-objectid'
|
||||
import { isValidObjectId } from 'mongoose'
|
||||
import mongoose from 'mongoose'
|
||||
import {
|
||||
buildVersionCollectionFields,
|
||||
type CreateVersion,
|
||||
@@ -12,8 +11,6 @@ import type { MongooseAdapter } from './index.js'
|
||||
import { sanitizeRelationshipIDs } from './utilities/sanitizeRelationshipIDs.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
const ObjectId = (ObjectIdImport.default ||
|
||||
ObjectIdImport) as unknown as typeof ObjectIdImport.default
|
||||
export const createVersion: CreateVersion = async function createVersion(
|
||||
this: MongooseAdapter,
|
||||
{
|
||||
@@ -60,10 +57,10 @@ export const createVersion: CreateVersion = async function createVersion(
|
||||
},
|
||||
],
|
||||
}
|
||||
if (typeof data.parent === 'string' && isValidObjectId(data.parent)) {
|
||||
if (data.parent instanceof mongoose.Types.ObjectId) {
|
||||
parentQuery.$or.push({
|
||||
parent: {
|
||||
$eq: ObjectId(data.parent),
|
||||
$eq: data.parent.toString(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { BaseDatabaseAdapter, DatabaseAdapterObj, Payload, UpdateOneArgs }
|
||||
import fs from 'fs'
|
||||
import mongoose from 'mongoose'
|
||||
import path from 'path'
|
||||
import { createDatabaseAdapter } from 'payload'
|
||||
import { createDatabaseAdapter, defaultBeginTransaction } from 'payload'
|
||||
|
||||
import type { CollectionModel, GlobalModel, MigrateDownArgs, MigrateUpArgs } from './types.js'
|
||||
|
||||
@@ -163,7 +163,7 @@ export function mongooseAdapter({
|
||||
url,
|
||||
versions: {},
|
||||
// DatabaseAdapter
|
||||
beginTransaction: transactionOptions ? beginTransaction : undefined,
|
||||
beginTransaction: transactionOptions === false ? defaultBeginTransaction() : beginTransaction,
|
||||
commitTransaction,
|
||||
connect,
|
||||
create,
|
||||
|
||||
@@ -12,6 +12,30 @@ type SanitizeQueryValueArgs = {
|
||||
val: any
|
||||
}
|
||||
|
||||
const buildExistsQuery = (formattedValue, path) => {
|
||||
if (formattedValue) {
|
||||
return {
|
||||
rawQuery: {
|
||||
$and: [
|
||||
{ [path]: { $exists: true } },
|
||||
{ [path]: { $ne: null } },
|
||||
{ [path]: { $ne: '' } }, // Exclude null and empty string
|
||||
],
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
rawQuery: {
|
||||
$or: [
|
||||
{ [path]: { $exists: false } },
|
||||
{ [path]: { $eq: null } },
|
||||
{ [path]: { $eq: '' } }, // Treat empty string as null / undefined
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ObjectId = (ObjectIdImport.default ||
|
||||
ObjectIdImport) as unknown as typeof ObjectIdImport.default
|
||||
export const sanitizeQueryValue = ({
|
||||
@@ -93,8 +117,16 @@ export const sanitizeQueryValue = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'number' && typeof formattedValue === 'string') {
|
||||
formattedValue = Number(val)
|
||||
if (field.type === 'number') {
|
||||
if (typeof formattedValue === 'string' && operator !== 'exists') {
|
||||
formattedValue = Number(val)
|
||||
}
|
||||
|
||||
if (operator === 'exists') {
|
||||
formattedValue = val === 'true' ? true : val === 'false' ? false : Boolean(val)
|
||||
|
||||
return buildExistsQuery(formattedValue, path)
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'date' && typeof val === 'string' && operator !== 'exists') {
|
||||
@@ -206,27 +238,7 @@ export const sanitizeQueryValue = ({
|
||||
if (operator === 'exists') {
|
||||
formattedValue = formattedValue === 'true' || formattedValue === true
|
||||
|
||||
if (formattedValue) {
|
||||
return {
|
||||
rawQuery: {
|
||||
$and: [
|
||||
{ [path]: { $exists: true } },
|
||||
{ [path]: { $ne: null } },
|
||||
{ [path]: { $ne: '' } },
|
||||
],
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
rawQuery: {
|
||||
$or: [
|
||||
{ [path]: { $exists: false } },
|
||||
{ [path]: { $eq: null } },
|
||||
{ [path]: { $eq: '' } }, // Treat empty string as null / undefined
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
return buildExistsQuery(formattedValue, path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-postgres",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -47,7 +47,7 @@ import {
|
||||
requireDrizzleKit,
|
||||
} from '@payloadcms/drizzle/postgres'
|
||||
import { pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
|
||||
import { createDatabaseAdapter } from 'payload'
|
||||
import { createDatabaseAdapter, defaultBeginTransaction } from 'payload'
|
||||
|
||||
import type { Args, PostgresAdapter } from './types.js'
|
||||
|
||||
@@ -107,7 +107,8 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
|
||||
versionsSuffix: args.versionsSuffix || '_v',
|
||||
|
||||
// DatabaseAdapter
|
||||
beginTransaction: args.transactionOptions === false ? undefined : beginTransaction,
|
||||
beginTransaction:
|
||||
args.transactionOptions === false ? defaultBeginTransaction() : beginTransaction,
|
||||
commitTransaction,
|
||||
connect,
|
||||
convertPathToJSONTraversal,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-sqlite",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The officially supported SQLite database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
updateVersion,
|
||||
} from '@payloadcms/drizzle'
|
||||
import { like } from 'drizzle-orm'
|
||||
import { createDatabaseAdapter } from 'payload'
|
||||
import { createDatabaseAdapter, defaultBeginTransaction } from 'payload'
|
||||
|
||||
import type { Args, SQLiteAdapter } from './types.js'
|
||||
|
||||
@@ -108,7 +108,7 @@ export function sqliteAdapter(args: Args): DatabaseAdapterObj<SQLiteAdapter> {
|
||||
versionsSuffix: args.versionsSuffix || '_v',
|
||||
|
||||
// DatabaseAdapter
|
||||
beginTransaction: args.transactionOptions ? beginTransaction : undefined,
|
||||
beginTransaction: args.transactionOptions ? beginTransaction : defaultBeginTransaction(),
|
||||
commitTransaction,
|
||||
connect,
|
||||
convertPathToJSONTraversal,
|
||||
|
||||
@@ -711,7 +711,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
withinLocalizedArrayOrBlock: withinLocalizedArrayOrBlock || field.localized,
|
||||
})
|
||||
|
||||
if (groupHasLocalizedField) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-vercel-postgres",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Vercel Postgres adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -47,7 +47,7 @@ import {
|
||||
requireDrizzleKit,
|
||||
} from '@payloadcms/drizzle/postgres'
|
||||
import { pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
|
||||
import { createDatabaseAdapter } from 'payload'
|
||||
import { createDatabaseAdapter, defaultBeginTransaction } from 'payload'
|
||||
|
||||
import type { Args, VercelPostgresAdapter } from './types.js'
|
||||
|
||||
@@ -107,7 +107,8 @@ export function vercelPostgresAdapter(args: Args = {}): DatabaseAdapterObj<Verce
|
||||
versionsSuffix: args.versionsSuffix || '_v',
|
||||
|
||||
// DatabaseAdapter
|
||||
beginTransaction: args.transactionOptions === false ? undefined : beginTransaction,
|
||||
beginTransaction:
|
||||
args.transactionOptions === false ? defaultBeginTransaction() : beginTransaction,
|
||||
commitTransaction,
|
||||
connect,
|
||||
convertPathToJSONTraversal,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/drizzle",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "A library of shared functions used by different payload database adapters",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -721,7 +721,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
withinLocalizedArrayOrBlock: withinLocalizedArrayOrBlock || field.localized,
|
||||
})
|
||||
|
||||
if (groupHasLocalizedField) {
|
||||
|
||||
@@ -237,12 +237,13 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
|
||||
if (field.type === 'blocks') {
|
||||
const blockFieldPath = `${sanitizedPath}${field.name}`
|
||||
const blocksByPath = blocks[blockFieldPath]
|
||||
|
||||
if (Array.isArray(blocks[blockFieldPath])) {
|
||||
if (Array.isArray(blocksByPath)) {
|
||||
if (field.localized) {
|
||||
result[field.name] = {}
|
||||
|
||||
blocks[blockFieldPath].forEach((row) => {
|
||||
blocksByPath.forEach((row) => {
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
delete row._uuid
|
||||
@@ -285,7 +286,23 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
})
|
||||
})
|
||||
} else {
|
||||
result[field.name] = blocks[blockFieldPath].reduce((acc, row, i) => {
|
||||
// Add locale-specific index to have a proper blockFieldPath for current locale
|
||||
// because blocks can be in the same array for different locales!
|
||||
if (withinArrayOrBlockLocale && config.localization) {
|
||||
for (const locale of config.localization.localeCodes) {
|
||||
let localeIndex = 0
|
||||
|
||||
for (let i = 0; i < blocksByPath.length; i++) {
|
||||
const row = blocksByPath[i]
|
||||
if (row._locale === locale) {
|
||||
row._index = localeIndex
|
||||
localeIndex++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result[field.name] = blocksByPath.reduce((acc, row, i) => {
|
||||
delete row._order
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
@@ -301,6 +318,10 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
if (row._locale) {
|
||||
delete row._locale
|
||||
}
|
||||
if (typeof row._index === 'number') {
|
||||
i = row._index
|
||||
delete row._index
|
||||
}
|
||||
|
||||
acc.push(
|
||||
traverseFields<T>({
|
||||
@@ -350,6 +371,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
}
|
||||
} else {
|
||||
const relationPathMatch = relationships[`${sanitizedPath}${field.name}`]
|
||||
|
||||
if (!relationPathMatch) {
|
||||
if ('hasMany' in field && field.hasMany) {
|
||||
if (field.localized && config.localization && config.localization.locales) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-nodemailer",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload Nodemailer Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-resend",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload Resend Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/graphql",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-react",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The official React SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-vue",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The official Vue SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The official live preview JavaScript SDK for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/next",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -37,7 +37,10 @@ export const getDocumentPermissions = async (args: {
|
||||
},
|
||||
req: {
|
||||
...req,
|
||||
data,
|
||||
data: {
|
||||
...data,
|
||||
_status: 'draft',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ export const getViewFromConfig = ({
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
if (segmentOne === 'reset') {
|
||||
if (`/${segmentOne}` === config.admin.routes.reset) {
|
||||
// --> /reset/:token
|
||||
ViewToRender = {
|
||||
Component: ResetPassword,
|
||||
|
||||
@@ -85,7 +85,7 @@ export const generatePageMetadata = async ({ config: configPromise, params }: Ar
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
if (segmentOne === 'reset') {
|
||||
if (`/${segmentOne}` === config.admin.routes.reset) {
|
||||
// --> /reset/:token
|
||||
meta = await generateResetPasswordMetadata({ config, i18n })
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
||||
"keywords": [
|
||||
"admin panel",
|
||||
|
||||
@@ -150,7 +150,7 @@ export const forgotPasswordOperation = async <TSlug extends CollectionSlug>(
|
||||
: `${protocol}//${req.headers.get('host')}`
|
||||
|
||||
let html = `${req.t('authentication:youAreReceivingResetPassword')}
|
||||
<a href="${serverURL}${config.routes.admin}/${config.admin.routes.reset}/${token}">${serverURL}${config.routes.admin}/${config.admin.routes.reset}/${token}</a>
|
||||
<a href="${serverURL}${config.routes.admin}${config.admin.routes.reset}/${token}">${serverURL}${config.routes.admin}${config.admin.routes.reset}/${token}</a>
|
||||
${req.t('authentication:youDidNotRequestPassword')}`
|
||||
|
||||
if (typeof collectionConfig.auth.forgotPassword.generateEmailHTML === 'function') {
|
||||
|
||||
9
packages/payload/src/database/defaultBeginTransaction.ts
Normal file
9
packages/payload/src/database/defaultBeginTransaction.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { BeginTransaction } from './types.js'
|
||||
|
||||
/**
|
||||
* Default implementation of `beginTransaction` that returns a resolved promise of null
|
||||
*/
|
||||
export function defaultBeginTransaction(): BeginTransaction {
|
||||
const promiseSingleton: Promise<null> = Promise.resolve(null)
|
||||
return () => promiseSingleton
|
||||
}
|
||||
@@ -9,11 +9,11 @@ export interface BaseDatabaseAdapter {
|
||||
* Start a transaction, requiring commitTransaction() to be called for any changes to be made.
|
||||
* @returns an identifier for the transaction or null if one cannot be established
|
||||
*/
|
||||
beginTransaction?: BeginTransaction
|
||||
beginTransaction: BeginTransaction
|
||||
/**
|
||||
* Persist the changes made since the start of the transaction.
|
||||
*/
|
||||
commitTransaction?: CommitTransaction
|
||||
commitTransaction: CommitTransaction
|
||||
|
||||
/**
|
||||
* Open the connection to the database
|
||||
@@ -116,7 +116,7 @@ export interface BaseDatabaseAdapter {
|
||||
/**
|
||||
* Abort any changes since the start of the transaction.
|
||||
*/
|
||||
rollbackTransaction?: RollbackTransaction
|
||||
rollbackTransaction: RollbackTransaction
|
||||
/**
|
||||
* A key-value store of all sessions open (used for transactions)
|
||||
*/
|
||||
|
||||
1
packages/payload/src/exports/i18n/da.ts
Normal file
1
packages/payload/src/exports/i18n/da.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { da } from '@payloadcms/translations/languages/da'
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SanitizedJoins } from '../../collections/config/types.js'
|
||||
import type { Config } from '../../config/types.js'
|
||||
import type { JoinField, RelationshipField } from './types.js'
|
||||
import type { JoinField, RelationshipField, UploadField } from './types.js'
|
||||
|
||||
import { APIError } from '../../errors/index.js'
|
||||
import { InvalidFieldJoin } from '../../errors/InvalidFieldJoin.js'
|
||||
@@ -33,7 +33,7 @@ export const sanitizeJoinField = ({
|
||||
if (!joinCollection) {
|
||||
throw new InvalidFieldJoin(field)
|
||||
}
|
||||
let joinRelationship: RelationshipField | undefined
|
||||
let joinRelationship: RelationshipField | UploadField
|
||||
|
||||
const pathSegments = field.on.split('.') // Split the schema path into segments
|
||||
let currentSegmentIndex = 0
|
||||
@@ -49,9 +49,10 @@ export const sanitizeJoinField = ({
|
||||
if ('name' in field && field.name === currentSegment) {
|
||||
// Check if this is the last segment in the path
|
||||
if (
|
||||
currentSegmentIndex === pathSegments.length - 1 &&
|
||||
'type' in field &&
|
||||
field.type === 'relationship'
|
||||
(currentSegmentIndex === pathSegments.length - 1 &&
|
||||
'type' in field &&
|
||||
field.type === 'relationship') ||
|
||||
field.type === 'upload'
|
||||
) {
|
||||
joinRelationship = field // Return the matched field
|
||||
next()
|
||||
|
||||
@@ -1125,6 +1125,7 @@ type SharedRelationshipPropertiesClient = FieldBaseClient &
|
||||
|
||||
type RelationshipAdmin = {
|
||||
allowCreate?: boolean
|
||||
allowEdit?: boolean
|
||||
components?: {
|
||||
Error?: CustomComponent<
|
||||
RelationshipFieldErrorClientComponent | RelationshipFieldErrorServerComponent
|
||||
@@ -1142,7 +1143,7 @@ type RelationshipAdminClient = {
|
||||
Label?: MappedComponent
|
||||
} & AdminClient['components']
|
||||
} & AdminClient &
|
||||
Pick<RelationshipAdmin, 'allowCreate' | 'isSortable'>
|
||||
Pick<RelationshipAdmin, 'allowCreate' | 'allowEdit' | 'isSortable'>
|
||||
|
||||
export type PolymorphicRelationshipField = {
|
||||
admin?: {
|
||||
|
||||
@@ -751,6 +751,7 @@ export { sanitizeConfig } from './config/sanitize.js'
|
||||
export type * from './config/types.js'
|
||||
export { combineQueries } from './database/combineQueries.js'
|
||||
export { createDatabaseAdapter } from './database/createDatabaseAdapter.js'
|
||||
export { defaultBeginTransaction } from './database/defaultBeginTransaction.js'
|
||||
export { default as flattenWhereToOperators } from './database/flattenWhereToOperators.js'
|
||||
export { getLocalizedPaths } from './database/getLocalizedPaths.js'
|
||||
export { createMigration } from './database/migrations/createMigration.js'
|
||||
|
||||
@@ -25,8 +25,7 @@ export async function initTransaction(req: PayloadRequest): Promise<boolean> {
|
||||
|
||||
return transactionID
|
||||
})
|
||||
await req.transactionID
|
||||
return !!req.transactionID
|
||||
return !!(await req.transactionID)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -15,5 +15,9 @@ export const getQueryDraftsSort = (sort: string): string => {
|
||||
orderBy = sort.substring(1)
|
||||
}
|
||||
|
||||
if (orderBy === 'id') {
|
||||
return `${direction}parent`
|
||||
}
|
||||
|
||||
return `${direction}version.${orderBy}`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud-storage",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The official cloud storage plugin for Payload CMS",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The official Payload Cloud plugin",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-form-builder",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Form builder plugin for Payload CMS",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-nested-docs",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The official Nested Docs plugin for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-redirects",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Redirects plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-search",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Search plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-seo",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "SEO plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-stripe",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Stripe plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-lexical",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -52,22 +52,22 @@
|
||||
"translateNewKeys": "node --no-deprecation --import @swc-node/register/esm-register scripts/translateNewKeys.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lexical/headless": "0.17.0",
|
||||
"@lexical/link": "0.17.0",
|
||||
"@lexical/list": "0.17.0",
|
||||
"@lexical/mark": "0.17.0",
|
||||
"@lexical/markdown": "0.17.0",
|
||||
"@lexical/react": "0.17.0",
|
||||
"@lexical/rich-text": "0.17.0",
|
||||
"@lexical/selection": "0.17.0",
|
||||
"@lexical/utils": "0.17.0",
|
||||
"@lexical/headless": "0.18.0",
|
||||
"@lexical/link": "0.18.0",
|
||||
"@lexical/list": "0.18.0",
|
||||
"@lexical/mark": "0.18.0",
|
||||
"@lexical/markdown": "0.18.0",
|
||||
"@lexical/react": "0.18.0",
|
||||
"@lexical/rich-text": "0.18.0",
|
||||
"@lexical/selection": "0.18.0",
|
||||
"@lexical/utils": "0.18.0",
|
||||
"@payloadcms/translations": "workspace:*",
|
||||
"@payloadcms/ui": "workspace:*",
|
||||
"@types/uuid": "10.0.0",
|
||||
"bson-objectid": "2.0.4",
|
||||
"dequal": "2.0.3",
|
||||
"escape-html": "1.0.3",
|
||||
"lexical": "0.17.0",
|
||||
"lexical": "0.18.0",
|
||||
"react-error-boundary": "4.0.13",
|
||||
"uuid": "10.0.0"
|
||||
},
|
||||
@@ -77,7 +77,7 @@
|
||||
"@babel/preset-env": "^7.24.5",
|
||||
"@babel/preset-react": "^7.24.1",
|
||||
"@babel/preset-typescript": "^7.24.1",
|
||||
"@lexical/eslint-plugin": "0.17.0",
|
||||
"@lexical/eslint-plugin": "0.18.0",
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"@types/escape-html": "1.0.4",
|
||||
"@types/json-schema": "7.0.15",
|
||||
@@ -95,18 +95,18 @@
|
||||
"peerDependencies": {
|
||||
"@faceless-ui/modal": "3.0.0-beta.2",
|
||||
"@faceless-ui/scroll-info": "2.0.0-beta.0",
|
||||
"@lexical/headless": "0.17.0",
|
||||
"@lexical/link": "0.17.0",
|
||||
"@lexical/list": "0.17.0",
|
||||
"@lexical/mark": "0.17.0",
|
||||
"@lexical/markdown": "0.17.0",
|
||||
"@lexical/react": "0.17.0",
|
||||
"@lexical/rich-text": "0.17.0",
|
||||
"@lexical/selection": "0.17.0",
|
||||
"@lexical/table": "0.17.0",
|
||||
"@lexical/utils": "0.17.0",
|
||||
"@lexical/headless": "0.18.0",
|
||||
"@lexical/link": "0.18.0",
|
||||
"@lexical/list": "0.18.0",
|
||||
"@lexical/mark": "0.18.0",
|
||||
"@lexical/markdown": "0.18.0",
|
||||
"@lexical/react": "0.18.0",
|
||||
"@lexical/rich-text": "0.18.0",
|
||||
"@lexical/selection": "0.18.0",
|
||||
"@lexical/table": "0.18.0",
|
||||
"@lexical/utils": "0.18.0",
|
||||
"@payloadcms/next": "workspace:*",
|
||||
"lexical": "0.17.0",
|
||||
"lexical": "0.18.0",
|
||||
"payload": "workspace:*",
|
||||
"react": "^19.0.0 || ^19.0.0-rc-5dcb0097-20240918",
|
||||
"react-dom": "^19.0.0 || ^19.0.0-rc-5dcb0097-20240918"
|
||||
|
||||
@@ -122,4 +122,10 @@ export {
|
||||
BlockNode,
|
||||
} from '../../features/blocks/client/nodes/BlocksNode.js'
|
||||
|
||||
export {
|
||||
$createInlineBlockNode,
|
||||
$isInlineBlockNode,
|
||||
InlineBlockNode,
|
||||
} from '../../features/blocks/client/nodes/InlineBlocksNode.js'
|
||||
|
||||
export { FieldsDrawer } from '../../utilities/fieldsDrawer/Drawer.js'
|
||||
|
||||
@@ -56,17 +56,20 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
|
||||
const $onDelete = useCallback(
|
||||
(event: KeyboardEvent) => {
|
||||
if (isSelected && $isNodeSelection($getSelection())) {
|
||||
const deleteSelection = $getSelection()
|
||||
if (isSelected && $isNodeSelection(deleteSelection)) {
|
||||
event.preventDefault()
|
||||
const node = $getNodeByKey(nodeKey)
|
||||
if ($isInlineBlockNode(node)) {
|
||||
node.remove()
|
||||
return true
|
||||
}
|
||||
editor.update(() => {
|
||||
deleteSelection.getNodes().forEach((node) => {
|
||||
if ($isInlineBlockNode(node)) {
|
||||
node.remove()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
return false
|
||||
},
|
||||
[isSelected, nodeKey],
|
||||
[editor, isSelected],
|
||||
)
|
||||
const onClick = useCallback(
|
||||
(payload: MouseEvent) => {
|
||||
|
||||
@@ -58,47 +58,6 @@ function computeSelectionCount(selection: TableSelection): {
|
||||
}
|
||||
}
|
||||
|
||||
// This is important when merging cells as there is no good way to re-merge weird shapes (a result
|
||||
// of selecting merged cells and non-merged)
|
||||
function isTableSelectionRectangular(selection: TableSelection): boolean {
|
||||
const nodes = selection.getNodes()
|
||||
const currentRows: Array<number> = []
|
||||
let currentRow: null | TableRowNode = null
|
||||
let expectedColumns: null | number = null
|
||||
let currentColumns = 0
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i]
|
||||
if ($isTableCellNode(node)) {
|
||||
const row = node.getParentOrThrow()
|
||||
if (!$isTableRowNode(row)) {
|
||||
throw new Error('Expected CellNode to have a RowNode parent')
|
||||
}
|
||||
if (currentRow !== row) {
|
||||
if (expectedColumns !== null && currentColumns !== expectedColumns) {
|
||||
return false
|
||||
}
|
||||
if (currentRow !== null) {
|
||||
expectedColumns = currentColumns
|
||||
}
|
||||
currentRow = row
|
||||
currentColumns = 0
|
||||
}
|
||||
const colSpan = node.__colSpan
|
||||
for (let j = 0; j < colSpan; j++) {
|
||||
if (currentRows[currentColumns + j] === undefined) {
|
||||
currentRows[currentColumns + j] = 0
|
||||
}
|
||||
currentRows[currentColumns + j] += node.__rowSpan
|
||||
}
|
||||
currentColumns += colSpan
|
||||
}
|
||||
}
|
||||
return (
|
||||
(expectedColumns === null || currentColumns === expectedColumns) &&
|
||||
currentRows.every((v) => v === currentRows[0])
|
||||
)
|
||||
}
|
||||
|
||||
function $canUnmerge(): boolean {
|
||||
const selection = $getSelection()
|
||||
if (
|
||||
@@ -183,10 +142,8 @@ function TableActionMenu({
|
||||
if ($isTableSelection(selection)) {
|
||||
const currentSelectionCounts = computeSelectionCount(selection)
|
||||
updateSelectionCounts(computeSelectionCount(selection))
|
||||
setCanMergeCells(
|
||||
isTableSelectionRectangular(selection) &&
|
||||
(currentSelectionCounts.columns > 1 || currentSelectionCounts.rows > 1),
|
||||
)
|
||||
|
||||
setCanMergeCells(currentSelectionCounts.columns > 1 || currentSelectionCounts.rows > 1)
|
||||
}
|
||||
// Unmerge cell
|
||||
setCanUnmergeCell($canUnmerge())
|
||||
@@ -252,9 +209,9 @@ function TableActionMenu({
|
||||
throw new Error('Expected to find tableElement in DOM')
|
||||
}
|
||||
|
||||
const tableSelection = getTableObserverFromTableElement(tableElement)
|
||||
if (tableSelection !== null) {
|
||||
tableSelection.clearHighlight()
|
||||
const tableObserver = getTableObserverFromTableElement(tableElement)
|
||||
if (tableObserver !== null) {
|
||||
tableObserver.clearHighlight()
|
||||
}
|
||||
|
||||
tableNode.markDirty()
|
||||
@@ -374,12 +331,13 @@ function TableActionMenu({
|
||||
throw new Error('Expected table row')
|
||||
}
|
||||
|
||||
const newStyle = tableCellNode.getHeaderStyles() ^ TableCellHeaderStates.ROW
|
||||
tableRow.getChildren().forEach((tableCell) => {
|
||||
if (!$isTableCellNode(tableCell)) {
|
||||
throw new Error('Expected table cell')
|
||||
}
|
||||
|
||||
tableCell.toggleHeaderStyle(TableCellHeaderStates.ROW)
|
||||
tableCell.setHeaderStyles(newStyle, TableCellHeaderStates.ROW)
|
||||
})
|
||||
|
||||
clearTableSelection()
|
||||
@@ -400,6 +358,7 @@ function TableActionMenu({
|
||||
throw new Error('Expected table cell to be inside of table row.')
|
||||
}
|
||||
|
||||
const newStyle = tableCellNode.getHeaderStyles() ^ TableCellHeaderStates.COLUMN
|
||||
for (let r = 0; r < tableRows.length; r++) {
|
||||
const tableRow = tableRows[r]
|
||||
|
||||
@@ -419,7 +378,20 @@ function TableActionMenu({
|
||||
throw new Error('Expected table cell')
|
||||
}
|
||||
|
||||
tableCell.toggleHeaderStyle(TableCellHeaderStates.COLUMN)
|
||||
tableCell.setHeaderStyles(newStyle, TableCellHeaderStates.COLUMN)
|
||||
}
|
||||
clearTableSelection()
|
||||
onClose()
|
||||
})
|
||||
}, [editor, tableCellNode, clearTableSelection, onClose])
|
||||
|
||||
const toggleRowStriping = useCallback(() => {
|
||||
editor.update(() => {
|
||||
if (tableCellNode.isAttached()) {
|
||||
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode)
|
||||
if (tableNode) {
|
||||
tableNode.setRowStriping(!tableNode.getRowStriping())
|
||||
}
|
||||
}
|
||||
|
||||
clearTableSelection()
|
||||
@@ -470,6 +442,14 @@ function TableActionMenu({
|
||||
</React.Fragment>
|
||||
) : null}
|
||||
|
||||
<button
|
||||
className="item"
|
||||
data-test-id="table-row-striping"
|
||||
onClick={() => toggleRowStriping()}
|
||||
type="button"
|
||||
>
|
||||
<span className="text">Toggle Row Striping</span>
|
||||
</button>
|
||||
<button
|
||||
className="item"
|
||||
data-test-id="table-insert-row-above"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { TableCellNode, TableDOMCell, TableMapType, TableMapValueType } from '@lexical/table'
|
||||
import type { TableCellNode, TableDOMCell, TableMapType } from '@lexical/table'
|
||||
import type { LexicalEditor } from 'lexical'
|
||||
import type { JSX, MouseEventHandler } from 'react'
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
$isTableCellNode,
|
||||
$isTableRowNode,
|
||||
getDOMCellFromTarget,
|
||||
TableNode,
|
||||
} from '@lexical/table'
|
||||
import { calculateZoomLevel } from '@lexical/utils'
|
||||
import { $getNearestNodeFromDOMNode } from 'lexical'
|
||||
@@ -32,7 +33,7 @@ type MousePosition = {
|
||||
type MouseDraggingDirection = 'bottom' | 'right'
|
||||
|
||||
const MIN_ROW_HEIGHT = 33
|
||||
const MIN_COLUMN_WIDTH = 50
|
||||
const MIN_COLUMN_WIDTH = 92
|
||||
|
||||
function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
const targetRef = useRef<HTMLElement | null>(null)
|
||||
@@ -59,6 +60,20 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
return (event.buttons & 1) === 1
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerNodeTransform(TableNode, (tableNode) => {
|
||||
if (tableNode.getColWidths()) {
|
||||
return tableNode
|
||||
}
|
||||
|
||||
const numColumns = tableNode.getColumnCount()
|
||||
const columnWidth = MIN_COLUMN_WIDTH
|
||||
|
||||
tableNode.setColWidths(Array(numColumns).fill(columnWidth))
|
||||
return tableNode
|
||||
})
|
||||
}, [editor])
|
||||
|
||||
useEffect(() => {
|
||||
const onMouseMove = (event: MouseEvent) => {
|
||||
setTimeout(() => {
|
||||
@@ -119,13 +134,12 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
}
|
||||
|
||||
const removeRootListener = editor.registerRootListener((rootElement, prevRootElement) => {
|
||||
rootElement?.addEventListener('mousemove', onMouseMove)
|
||||
rootElement?.addEventListener('mousedown', onMouseDown)
|
||||
rootElement?.addEventListener('mouseup', onMouseUp)
|
||||
|
||||
prevRootElement?.removeEventListener('mousemove', onMouseMove)
|
||||
prevRootElement?.removeEventListener('mousedown', onMouseDown)
|
||||
prevRootElement?.removeEventListener('mouseup', onMouseUp)
|
||||
rootElement?.addEventListener('mousemove', onMouseMove)
|
||||
rootElement?.addEventListener('mousedown', onMouseDown)
|
||||
rootElement?.addEventListener('mouseup', onMouseUp)
|
||||
})
|
||||
|
||||
return () => {
|
||||
@@ -155,7 +169,8 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
|
||||
const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode)
|
||||
|
||||
const tableRowIndex = $getTableRowIndexFromTableCellNode(tableCellNode)
|
||||
const tableRowIndex =
|
||||
$getTableRowIndexFromTableCellNode(tableCellNode) + tableCellNode.getRowSpan() - 1
|
||||
|
||||
const tableRows = tableNode.getChildren()
|
||||
|
||||
@@ -186,27 +201,6 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
[activeCell, editor],
|
||||
)
|
||||
|
||||
const getCellNodeWidth = (
|
||||
cell: TableCellNode,
|
||||
activeEditor: LexicalEditor,
|
||||
): number | undefined => {
|
||||
const width = cell.getWidth()
|
||||
if (width !== undefined) {
|
||||
return width
|
||||
}
|
||||
|
||||
const domCellNode = activeEditor.getElementByKey(cell.getKey())
|
||||
if (domCellNode == null) {
|
||||
return undefined
|
||||
}
|
||||
const computedStyle = getComputedStyle(domCellNode)
|
||||
return (
|
||||
domCellNode.clientWidth -
|
||||
parseFloat(computedStyle.paddingLeft) -
|
||||
parseFloat(computedStyle.paddingRight)
|
||||
)
|
||||
}
|
||||
|
||||
const getCellNodeHeight = (
|
||||
cell: TableCellNode,
|
||||
activeEditor: LexicalEditor,
|
||||
@@ -244,21 +238,18 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
throw new Error('TableCellResizer: Table column not found.')
|
||||
}
|
||||
|
||||
for (let row = 0; row < tableMap.length; row++) {
|
||||
const cell: TableMapValueType = tableMap[row][columnIndex]
|
||||
if (
|
||||
cell.startRow === row &&
|
||||
(columnIndex === tableMap[row].length - 1 ||
|
||||
tableMap[row][columnIndex].cell !== tableMap[row][columnIndex + 1].cell)
|
||||
) {
|
||||
const width = getCellNodeWidth(cell.cell, editor)
|
||||
if (width === undefined) {
|
||||
continue
|
||||
}
|
||||
const newWidth = Math.max(width + widthChange, MIN_COLUMN_WIDTH)
|
||||
cell.cell.setWidth(newWidth)
|
||||
}
|
||||
const colWidths = tableNode.getColWidths()
|
||||
if (!colWidths) {
|
||||
return
|
||||
}
|
||||
const width = colWidths[columnIndex]
|
||||
if (width === undefined) {
|
||||
return
|
||||
}
|
||||
const newColWidths = [...colWidths]
|
||||
const newWidth = Math.max(width + widthChange, MIN_COLUMN_WIDTH)
|
||||
newColWidths[columnIndex] = newWidth
|
||||
tableNode.setColWidths(newColWidths)
|
||||
},
|
||||
{ tag: 'skip-scroll-into-view' },
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
overflow-y: scroll;
|
||||
overflow-x: scroll;
|
||||
table-layout: fixed;
|
||||
width: max-content;
|
||||
width: fit-content;
|
||||
margin: 0 25px 30px 0;
|
||||
|
||||
::selection {
|
||||
@@ -20,13 +20,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__tableRowStriping tr:nth-child(even) {
|
||||
background-color: var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
&__tableSelected {
|
||||
outline: 2px solid rgb(60, 132, 244);
|
||||
}
|
||||
|
||||
&__tableCell {
|
||||
border: 1px solid var(--theme-elevation-200);
|
||||
min-width: 75px;
|
||||
vertical-align: top;
|
||||
text-align: start;
|
||||
padding: 6px 8px;
|
||||
|
||||
@@ -118,7 +118,7 @@ export const TablePlugin: PluginComponent = () => {
|
||||
COMMAND_PRIORITY_EDITOR,
|
||||
),
|
||||
)
|
||||
}, [cellContext, editor, toggleModal])
|
||||
}, [cellContext, drawerSlug, editor, toggleModal])
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
|
||||
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection.js'
|
||||
import { addClassNamesToElement, mergeRegister, removeClassNamesFromElement } from '@lexical/utils'
|
||||
import {
|
||||
$getNodeByKey,
|
||||
$getSelection,
|
||||
$isNodeSelection,
|
||||
CLICK_COMMAND,
|
||||
@@ -31,17 +30,20 @@ export function HorizontalRuleComponent({ nodeKey }: { nodeKey: NodeKey }) {
|
||||
|
||||
const $onDelete = useCallback(
|
||||
(event: KeyboardEvent) => {
|
||||
if (isSelected && $isNodeSelection($getSelection())) {
|
||||
const deleteSelection = $getSelection()
|
||||
if (isSelected && $isNodeSelection(deleteSelection)) {
|
||||
event.preventDefault()
|
||||
const node = $getNodeByKey(nodeKey)
|
||||
if ($isHorizontalRuleNode(node)) {
|
||||
node.remove()
|
||||
return true
|
||||
}
|
||||
editor.update(() => {
|
||||
deleteSelection.getNodes().forEach((node) => {
|
||||
if ($isHorizontalRuleNode(node)) {
|
||||
node.remove()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
return false
|
||||
},
|
||||
[isSelected, nodeKey],
|
||||
[editor, isSelected],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -99,18 +99,21 @@ const Component: React.FC<Props> = (props) => {
|
||||
|
||||
const $onDelete = useCallback(
|
||||
(payload: KeyboardEvent) => {
|
||||
if (isSelected && $isNodeSelection($getSelection())) {
|
||||
const deleteSelection = $getSelection()
|
||||
if (isSelected && $isNodeSelection(deleteSelection)) {
|
||||
const event: KeyboardEvent = payload
|
||||
event.preventDefault()
|
||||
const node = $getNodeByKey(nodeKey!)
|
||||
if ($isRelationshipNode(node)) {
|
||||
node.remove()
|
||||
return true
|
||||
}
|
||||
editor.update(() => {
|
||||
deleteSelection.getNodes().forEach((node) => {
|
||||
if ($isRelationshipNode(node)) {
|
||||
node.remove()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
return false
|
||||
},
|
||||
[isSelected, nodeKey],
|
||||
[editor, isSelected],
|
||||
)
|
||||
const onClick = useCallback(
|
||||
(payload: MouseEvent) => {
|
||||
|
||||
@@ -126,17 +126,20 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
|
||||
const $onDelete = useCallback(
|
||||
(event: KeyboardEvent) => {
|
||||
if (isSelected && $isNodeSelection($getSelection())) {
|
||||
const deleteSelection = $getSelection()
|
||||
if (isSelected && $isNodeSelection(deleteSelection)) {
|
||||
event.preventDefault()
|
||||
const node = $getNodeByKey(nodeKey)
|
||||
if ($isUploadNode(node)) {
|
||||
node.remove()
|
||||
return true
|
||||
}
|
||||
editor.update(() => {
|
||||
deleteSelection.getNodes().forEach((node) => {
|
||||
if ($isUploadNode(node)) {
|
||||
node.remove()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
return false
|
||||
},
|
||||
[isSelected, nodeKey],
|
||||
[editor, isSelected],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -61,7 +61,7 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte
|
||||
'@lexical/selection',
|
||||
'@lexical/utils',
|
||||
],
|
||||
targetVersion: '0.17.0',
|
||||
targetVersion: '0.18.0',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
@@ -221,19 +221,34 @@
|
||||
|
||||
&__listItem {
|
||||
font-size: base(0.8);
|
||||
margin: 0 0 0.4em base(0.8);
|
||||
margin: 0 0 0.4em 40px;
|
||||
}
|
||||
|
||||
&__listItem[dir='rtl'] {
|
||||
margin: 0 40px 0.4em 0;
|
||||
}
|
||||
|
||||
&__listItemChecked,
|
||||
&__listItemUnchecked {
|
||||
position: relative;
|
||||
margin-inline: 0;
|
||||
padding-left: base(1.2);
|
||||
padding-right: base(1.2);
|
||||
// Instead of having margin-left: 40px like other list-items or indented paragraphs,
|
||||
// we use padding-left: 25px + margin-left: 15px = 40px, so that the click position
|
||||
// calculation in `CheckListPlugin` matches the checkbox
|
||||
margin-left: 15px;
|
||||
padding-left: 25px;
|
||||
list-style-type: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
// See comment above for why we need this
|
||||
&__listItemUnchecked[dir='rtl'],
|
||||
&__listItemChecked[dir='rtl'] {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 25px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
&__listItemChecked {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ export const LexicalEditorTheme: EditorThemeClasses = {
|
||||
tableCellSelected: 'LexicalEditorTheme__tableCellSelected',
|
||||
tableCellSortedIndicator: 'LexicalEditorTheme__tableCellSortedIndicator',
|
||||
tableResizeRuler: 'LexicalEditorTheme__tableCellResizeRuler',
|
||||
tableRowStriping: 'LexicalEditorTheme__tableRowStriping',
|
||||
tableSelected: 'LexicalEditorTheme__tableSelected',
|
||||
text: {
|
||||
bold: 'LexicalEditorTheme__textBold',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-slate",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "The officially supported Slate richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-azure",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload storage adapter for Azure Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-gcs",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload storage adapter for Google Cloud Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-s3",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload storage adapter for Amazon S3",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-uploadthing",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload storage adapter for uploadthing",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-vercel-blob",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"description": "Payload storage adapter for Vercel Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/translations",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ar } from '../languages/ar.js'
|
||||
import { az } from '../languages/az.js'
|
||||
import { bg } from '../languages/bg.js'
|
||||
import { cs } from '../languages/cs.js'
|
||||
import { da } from '../languages/da.js'
|
||||
import { de } from '../languages/de.js'
|
||||
import { en } from '../languages/en.js'
|
||||
import { es } from '../languages/es.js'
|
||||
@@ -38,6 +39,7 @@ export const translations = {
|
||||
az,
|
||||
bg,
|
||||
cs,
|
||||
da,
|
||||
de,
|
||||
en,
|
||||
es,
|
||||
|
||||
@@ -19,6 +19,10 @@ export const importDateFNSLocale = async (locale: string): Promise<Locale> => {
|
||||
case 'cs':
|
||||
result = (await import('date-fns/locale/cs')).cs
|
||||
|
||||
break
|
||||
case 'da':
|
||||
result = (await import('date-fns/locale/da')).da
|
||||
|
||||
break
|
||||
case 'de':
|
||||
result = (await import('date-fns/locale/de')).de
|
||||
|
||||
456
packages/translations/src/languages/da.ts
Normal file
456
packages/translations/src/languages/da.ts
Normal file
@@ -0,0 +1,456 @@
|
||||
import type { DefaultTranslationsObject, Language } from '../types.js'
|
||||
|
||||
export const daTranslations: DefaultTranslationsObject = {
|
||||
authentication: {
|
||||
account: 'Konto',
|
||||
accountOfCurrentUser: 'Den nuværende brugers konto',
|
||||
accountVerified: 'Konto verifieret.',
|
||||
alreadyActivated: 'Allerede aktiveret',
|
||||
alreadyLoggedIn: 'Allerede logget ind',
|
||||
apiKey: 'API nøgle',
|
||||
authenticated: 'Godkendt',
|
||||
backToLogin: 'Tilbage til login',
|
||||
beginCreateFirstUser: 'For at starte, opret en bruger.',
|
||||
changePassword: 'Skift adgangskode',
|
||||
checkYourEmailForPasswordReset:
|
||||
'Tjek din email for at finde linket der vil give adgang til at ændre din adgangskode',
|
||||
confirmGeneration: 'Bekræft generering',
|
||||
confirmPassword: 'Bekræft adgangskode',
|
||||
createFirstUser: 'Opret bruger',
|
||||
emailNotValid: 'Ugyldig email',
|
||||
emailOrUsername: 'Email eller brugernavn',
|
||||
emailSent: 'Email sendt',
|
||||
emailVerified: 'Email verificeret.',
|
||||
enableAPIKey: 'Aktiver API nøgle',
|
||||
failedToUnlock: 'Kunne ikke låse op',
|
||||
forceUnlock: 'Tving oplåsning',
|
||||
forgotPassword: 'Glemt adgangskode',
|
||||
forgotPasswordEmailInstructions:
|
||||
'Indtast email nedenunder. Du vil modtage en email med instruktioner i hvordan du nulstiller din adgangskode.',
|
||||
forgotPasswordQuestion: 'Glemt adgangskode?',
|
||||
forgotPasswordUsernameInstructions:
|
||||
'Indtast brugernavn nedenunder. Instruktioner i hvordan du nulstiller din adgangskode vil blive sendt til den email der er tilknyttet brugeren.',
|
||||
generate: 'Generer',
|
||||
generateNewAPIKey: 'Generer ny API nøgle.',
|
||||
generatingNewAPIKeyWillInvalidate:
|
||||
'Generering af en ny API nøgle vil <1>ugyldiggøre</1> den tidligere nøgle. Vil du forsætte?',
|
||||
lockUntil: 'Lås indtil',
|
||||
logBackIn: 'Log på igen',
|
||||
loggedIn: 'For at logge på med en anden bruger, skal du først <0>logge ud</0>.',
|
||||
loggedInChangePassword: 'For at ændre din adgangskode, gå til <0>konto</0> og ændr den der.',
|
||||
loggedOutInactivity: 'Du er blevet logget ud grundet inaktivitet.',
|
||||
loggedOutSuccessfully: 'Du er logget ud.',
|
||||
loggingOut: 'Logger ud...',
|
||||
login: 'Login',
|
||||
loginAttempts: 'Login forsøg',
|
||||
loginUser: 'Login bruger',
|
||||
loginWithAnotherUser: 'For at logge på med en anden bruger, skal du først <0>logge ud</0>.',
|
||||
logOut: 'Log ud',
|
||||
logout: 'Log ud',
|
||||
logoutSuccessful: 'Log ud succesfuldt.',
|
||||
logoutUser: 'Log ud bruger',
|
||||
newAccountCreated:
|
||||
'En ny bruger er blevet oprettet. <a href="{{serverURL}}">{{serverURL}}</a> Klik på linket eller kopier URL for at verificere din email: <a href="{{verificationURL}}">{{verificationURL}}</a><br> Efter verificeringen af din email, kan du logge ind.',
|
||||
newAPIKeyGenerated: 'Ny API nøgle genereret.',
|
||||
newPassword: 'Ny adgangskode',
|
||||
passed: 'Godkendt',
|
||||
passwordResetSuccessfully: 'Adgangskode nulstillet.',
|
||||
resetPassword: 'Nulstil adgangskode',
|
||||
resetPasswordExpiration: 'Nulstil udløbsdato for adgangskoden',
|
||||
resetPasswordToken: 'Nulstil adgangskode token',
|
||||
resetYourPassword: 'Nulstil din adgangskode',
|
||||
stayLoggedIn: 'Forbliv logget ind',
|
||||
successfullyRegisteredFirstUser: 'Bruger registreret.',
|
||||
successfullyUnlocked: 'Låst op',
|
||||
tokenRefreshSuccessful: 'Tokenopdatering blev gennemført med succes.',
|
||||
unableToVerify: 'Kan ikke verificere',
|
||||
username: 'Brugernavn',
|
||||
usernameNotValid: 'Brugernavnet er ugyldigt.',
|
||||
verified: 'Bekræftet',
|
||||
verifiedSuccessfully: 'Bekræftet succesfuldt',
|
||||
verify: 'Bekræft',
|
||||
verifyUser: 'Bekræft bruger',
|
||||
verifyYourEmail: 'Bekræft din email',
|
||||
youAreInactive:
|
||||
'Du har ikke været aktiv i et stykke tid og vil snart blive logget automatisk ud. Vil du forblive logget ind?',
|
||||
youAreReceivingResetPassword:
|
||||
'Du modtager dette, fordi du eller en anden har anmodet om at nulstille adgangskoden til din konto. Klik venligst på følgende link, eller indsæt det i din browser for at fuldføre processen:',
|
||||
youDidNotRequestPassword:
|
||||
'Hvis du ikke har anmodet om dette, skal du blot ignorere denne e-mail, og din adgangskode vil forblive uændret',
|
||||
},
|
||||
error: {
|
||||
accountAlreadyActivated: 'Denne konto er allerede blevet aktiveret.',
|
||||
autosaving: 'Der opstod et problem under autosaving af dette dokument.',
|
||||
correctInvalidFields: 'Venligst korriger ugyldige felter.',
|
||||
deletingFile: 'Der opstod en fejl under sletning af filen.',
|
||||
deletingTitle:
|
||||
'Der opstod en fejl under sletningen {{title}}. Tjek din forbindelse eller prøv igen.',
|
||||
emailOrPasswordIncorrect: 'Email eller brugernavn er forkert.',
|
||||
followingFieldsInvalid_one: 'Feltet er ugyldigt:',
|
||||
followingFieldsInvalid_other: 'Felterne er ugyldige:',
|
||||
incorrectCollection: 'Forkert samling',
|
||||
invalidFileType: 'Ugyldig filtype',
|
||||
invalidFileTypeValue: 'Ugyldig filtype: {{value}}',
|
||||
loadingDocument: 'Der opstod et problem med at loade dokumentet med ID {{id}}.',
|
||||
localesNotSaved_one: 'Følgende lokalitet kunne ikke gemmes:',
|
||||
localesNotSaved_other: 'Følgende lokaliteter kunne ikke gemmes:',
|
||||
logoutFailed: 'Log ud mislykket.',
|
||||
missingEmail: 'Mangler email.',
|
||||
missingIDOfDocument: 'Mangler ID af dokument til opdatering.',
|
||||
missingIDOfVersion: 'ID for version mangler.',
|
||||
missingRequiredData: 'Mangler påkrævet data.',
|
||||
noFilesUploaded: 'Ingen filer blev uploadet.',
|
||||
noMatchedField: 'Ingen matchende felt fundet for "{{label}}"',
|
||||
notAllowedToAccessPage: 'Du har ikke adgang til denne side.',
|
||||
notAllowedToPerformAction: 'Du har ikke adgang til denne handling.',
|
||||
notFound: 'Den anmodede ressource blev ikke fundet.',
|
||||
noUser: 'Ingen bruger',
|
||||
previewing: 'Der opstod et problem med at vise dokumentet.',
|
||||
problemUploadingFile: 'Der opstod et problem under uploadingen af filen.',
|
||||
tokenInvalidOrExpired: 'Token er enten ugyldig eller udløbet.',
|
||||
tokenNotProvided: 'Token ikke angivet.',
|
||||
unableToDeleteCount: 'Kunne ikke slette {{count}} mangler {{total}} {{label}}.',
|
||||
unableToUpdateCount: 'Kunne ikke slette {{count}} mangler {{total}} {{label}}.',
|
||||
unauthorized: 'Uautoriseret, log in for at gennemføre handlingen.',
|
||||
unknown: 'En ukendt fejl er opstået.',
|
||||
unPublishingDocument: 'Der opstod et problem med at ophæve udgivelsen af dette dokument.',
|
||||
unspecific: 'En fejl er opstået.',
|
||||
userEmailAlreadyRegistered: 'Email allerede registreret.',
|
||||
userLocked: 'Denne bruger er låst på grund af for mange fejlede loginforsøg',
|
||||
usernameAlreadyRegistered: 'Brugernavn allerede registeret.',
|
||||
usernameOrPasswordIncorrect: 'Bruger navn eller adgangskode er forkert.',
|
||||
valueMustBeUnique: 'Værdien skal være unik',
|
||||
verificationTokenInvalid: 'Verifikationstoken er ugyldigt.',
|
||||
},
|
||||
fields: {
|
||||
addLabel: 'Tilføj {{label}}',
|
||||
addLink: 'Tilføj Link',
|
||||
addNew: 'Tilføj ny',
|
||||
addNewLabel: 'Tilføj ny {{label}}',
|
||||
addRelationship: 'Tilføj forhold',
|
||||
addUpload: 'Tilføj upload',
|
||||
block: 'blok',
|
||||
blocks: 'blokke',
|
||||
blockType: 'Blok type',
|
||||
chooseBetweenCustomTextOrDocument:
|
||||
'Vælg mellem at indtaste en brugerdefineret tekst-URL eller linke til et andet dokument.',
|
||||
chooseDocumentToLink: 'Vælg et dokument at linke til',
|
||||
chooseFromExisting: 'Vælg fra eksiterende',
|
||||
chooseLabel: 'Vælg {{label}}',
|
||||
collapseAll: 'Skjul alt"',
|
||||
customURL: 'Brugerdefineret URL',
|
||||
editLabelData: 'Rediger {{label}} data',
|
||||
editLink: 'Rediger link',
|
||||
editRelationship: 'Rediger forhold',
|
||||
enterURL: 'Indtast URL',
|
||||
internalLink: 'Intern link',
|
||||
itemsAndMore: '{{items}} og {{count}} mere',
|
||||
labelRelationship: '{{label}} forhold',
|
||||
latitude: 'breddegrad',
|
||||
linkedTo: 'Linket til <0>{{label}}</0>',
|
||||
linkType: 'Link type',
|
||||
longitude: 'Længdegrad',
|
||||
newLabel: 'Ny {{label}}',
|
||||
openInNewTab: 'Åben i ny fane',
|
||||
passwordsDoNotMatch: 'Adgangskoder matcher ikke.',
|
||||
relatedDocument: 'Relateret dokument',
|
||||
relationTo: 'Relateret til',
|
||||
removeRelationship: 'Fjern forhold',
|
||||
removeUpload: 'Fjern upload',
|
||||
saveChanges: 'Gem ændringer',
|
||||
searchForBlock: 'Søg efter blok',
|
||||
selectExistingLabel: 'Vælg eksisterende {{label}}',
|
||||
selectFieldsToEdit: 'Vælg felter at redigere',
|
||||
showAll: 'Vis alle',
|
||||
swapRelationship: 'Byt forhold',
|
||||
swapUpload: 'Byt upload',
|
||||
textToDisplay: 'Tekst der skal vises',
|
||||
toggleBlock: 'Skift blok',
|
||||
uploadNewLabel: 'Upload ny {{label}}',
|
||||
},
|
||||
general: {
|
||||
aboutToDelete: 'Du er ved at slette {{label}} <1>{{title}}</1>. Er du sikker?',
|
||||
aboutToDeleteCount_many: 'Du er ved at slette {{count}} {{label}}',
|
||||
aboutToDeleteCount_one: 'Du er ved at slette {{count}} {{label}}',
|
||||
aboutToDeleteCount_other: 'Du er ved at slette {{count}} {{label}}',
|
||||
addBelow: 'Tilføj under',
|
||||
addFilter: 'Tilføj filter',
|
||||
adminTheme: 'Admin tema',
|
||||
and: 'Og',
|
||||
anotherUserTakenOver: 'En anden bruger har overtaget denne ressource.',
|
||||
applyChanges: 'Tilføj ændringer',
|
||||
ascending: 'Stigende',
|
||||
automatic: 'Automatisk',
|
||||
backToDashboard: 'Tilbage til dashboard',
|
||||
cancel: 'Anuller',
|
||||
changesNotSaved:
|
||||
'Dine ændringer er ikke blevet gemt. Hvis du forlader siden, vil din ændringer gå tabt.',
|
||||
clearAll: 'Ryd alt',
|
||||
close: 'Luk',
|
||||
collapse: 'Skjul',
|
||||
collections: 'Samlinger',
|
||||
columns: 'Kolonner',
|
||||
columnToSort: 'Kolonne at sortere',
|
||||
confirm: 'Bekræft',
|
||||
confirmDeletion: 'Bekræft sletning',
|
||||
confirmDuplication: 'Bekræft duplikering',
|
||||
copied: 'Kopieret',
|
||||
copy: 'Kopier',
|
||||
create: 'Opret',
|
||||
created: 'Oprettet',
|
||||
createdAt: 'Oprettet til',
|
||||
createNew: 'Opret ny',
|
||||
createNewLabel: 'Opret ny {{label}}',
|
||||
creating: 'Opretter',
|
||||
creatingNewLabel: 'Opretter ny {{label}}',
|
||||
currentlyEditing: 'Du redigerer i øjeblikket',
|
||||
custom: 'Tilpasset',
|
||||
dark: 'Mørk',
|
||||
dashboard: 'Dashboard',
|
||||
delete: 'Slet',
|
||||
deletedCountSuccessfully: 'Slettet {{count}} {{label}}.',
|
||||
deletedSuccessfully: 'Slettet.',
|
||||
deleting: 'Sletter...',
|
||||
depth: 'Dybde',
|
||||
descending: 'Faldende',
|
||||
deselectAllRows: 'Fjern markering af alle rækker',
|
||||
document: 'Dokument',
|
||||
documentLocked: 'Dette dokument er låst',
|
||||
documents: 'Dokumenter',
|
||||
duplicate: 'Duplikér',
|
||||
duplicateWithoutSaving: 'Dupliker uden at gemme ændringer',
|
||||
edit: 'Redigere',
|
||||
editedSince: 'Dette dokument er blevet redigeret siden du startede',
|
||||
editing: 'Rediger',
|
||||
editingLabel_many: 'Rediger {{count}} {{label}}',
|
||||
editingLabel_one: 'Rediger {{count}} {{label}}',
|
||||
editingLabel_other: 'Rediger {{count}} {{label}}',
|
||||
editingTakenOver: 'En anden bruger har overtaget redigeringen af dette dokument',
|
||||
editLabel: 'Redigere {{label}}',
|
||||
email: 'Email',
|
||||
emailAddress: 'e-mailadresse',
|
||||
enterAValue: 'Indtast en værdi',
|
||||
error: 'Fejl',
|
||||
errors: 'Fejl',
|
||||
fallbackToDefaultLocale: 'Tilbagefald til standardlokalitet',
|
||||
false: 'Falsk',
|
||||
filter: 'Filter',
|
||||
filters: 'Filtre',
|
||||
filterWhere: 'Filter {{label}} hvor',
|
||||
globals: 'Globale',
|
||||
goBack: 'Gå tilbage',
|
||||
isEditing: 'redigerer',
|
||||
language: 'Sprog',
|
||||
lastModified: 'Sidst ændret',
|
||||
leaveAnyway: 'Forlad alligevel',
|
||||
leaveWithoutSaving: 'Forlad uden at gemme',
|
||||
light: 'Lys',
|
||||
livePreview: 'Live-forhåndsvisning',
|
||||
loading: 'Loader',
|
||||
locale: 'Lokalitet',
|
||||
locales: 'Lokaliteter',
|
||||
menu: 'Menu',
|
||||
moveDown: 'Ryk ned',
|
||||
moveUp: 'Ryk op',
|
||||
newPassword: 'Ny adgangskode',
|
||||
next: 'Næste',
|
||||
noFiltersSet: 'Ingen filtre angivet',
|
||||
noLabel: '<Ingen {{label}}>',
|
||||
none: 'Ingen',
|
||||
noOptions: 'Ingen muligheder',
|
||||
noResults:
|
||||
'No {{label}} fundet. Enten findes der endnu ingen {{label}}, eller også matcher ingen af de filtre angivet ovenfor.',
|
||||
notFound: 'Ikke fundet',
|
||||
nothingFound: 'Intet fundet',
|
||||
noValue: 'Ingen værdi',
|
||||
of: 'Af',
|
||||
only: 'kun',
|
||||
open: 'Åben',
|
||||
or: 'Eller',
|
||||
order: 'Rækkefølge',
|
||||
pageNotFound: 'Siden blev ikke fundet',
|
||||
password: 'Adgangskode',
|
||||
payloadSettings: 'Payload-indstillinger',
|
||||
perPage: 'Per side: {{limit}}',
|
||||
previous: 'Tidligere',
|
||||
remove: 'Fjern',
|
||||
reset: 'Nulstil',
|
||||
row: 'Række',
|
||||
rows: 'Rækker',
|
||||
save: 'Gem',
|
||||
saving: 'Gemmer...',
|
||||
searchBy: 'Søg efter {{label}}',
|
||||
selectAll: 'Vælg alle {{count}} {{label}}',
|
||||
selectAllRows: 'Vælg alle rækker',
|
||||
selectedCount: '{{count}} {{label}} valgt',
|
||||
selectValue: 'Vælg en værdi',
|
||||
showAllLabel: 'Vis alle {{label}}',
|
||||
sorryNotFound: 'Beklager—der er intet, der svarer til din handling.',
|
||||
sort: 'Sorter',
|
||||
sortByLabelDirection: 'Sorter efter {{label}} {{direction}}',
|
||||
stayOnThisPage: 'Forbliv på siden',
|
||||
submissionSuccessful: 'Indsendt.',
|
||||
submit: 'Send',
|
||||
submitting: 'Sender...',
|
||||
success: 'Succes',
|
||||
successfullyCreated: '{{label}} oprettet.',
|
||||
successfullyDuplicated: '{{label}} duplikeret.',
|
||||
takeOver: 'Overtag',
|
||||
thisLanguage: 'Dansk',
|
||||
titleDeleted: '{{label}} "{{title}}" slettet.',
|
||||
true: 'Sandt',
|
||||
unauthorized: 'Uautoriseret',
|
||||
unsavedChangesDuplicate: 'Du har ikke-gemte ændringer. Vil du fortsætte med at duplikere?',
|
||||
untitled: 'Uden titel',
|
||||
updatedAt: 'Opdateret ved',
|
||||
updatedCountSuccessfully: 'Opdateret {{count}} {{label}} successfully.',
|
||||
updatedSuccessfully: 'Opdateret.',
|
||||
updating: 'Opdaterer',
|
||||
uploading: 'Uploader',
|
||||
user: 'Bruger',
|
||||
username: 'Brugernavn',
|
||||
users: 'Brugere',
|
||||
value: 'Værdi',
|
||||
viewReadOnly: 'Vis kun-læsning',
|
||||
welcome: 'Velkommen',
|
||||
},
|
||||
operators: {
|
||||
contains: 'Indeholder',
|
||||
equals: 'Lig med',
|
||||
exists: 'Eksisterer',
|
||||
intersects: 'Intersekterer',
|
||||
isGreaterThan: 'Er større end',
|
||||
isGreaterThanOrEqualTo: 'Er større end eller lig med',
|
||||
isIn: 'Er i',
|
||||
isLessThan: 'Er mindre end',
|
||||
isLessThanOrEqualTo: 'Er mindre end eller lig med',
|
||||
isLike: 'Ligner',
|
||||
isNotEqualTo: 'Er ikke lig med',
|
||||
isNotIn: 'Er ikke i',
|
||||
near: 'Tæt på',
|
||||
within: 'Inden for',
|
||||
},
|
||||
upload: {
|
||||
addFile: 'Tilføj fil',
|
||||
addFiles: 'Tilføj Filer',
|
||||
bulkUpload: 'Masseupload',
|
||||
crop: 'Beskær',
|
||||
cropToolDescription:
|
||||
'Træk i hjørnerne af det valgte område, tegn et nyt område eller juster værdierne nedenfor.',
|
||||
dragAndDrop: 'Træk og slip en fil',
|
||||
dragAndDropHere: 'Eller træk og slip en fil her',
|
||||
editImage: 'Rediger billede',
|
||||
fileName: 'Filnavn',
|
||||
fileSize: 'Filstørrelse',
|
||||
filesToUpload: 'Filer til upload',
|
||||
fileToUpload: 'Fil til upload',
|
||||
focalPoint: 'Fokuspunkt',
|
||||
focalPointDescription:
|
||||
'Træk fokuspunktet direkte på forhåndsvisningen eller juster værdierne nedenfor.',
|
||||
height: 'Højde',
|
||||
lessInfo: 'Mindre info',
|
||||
moreInfo: 'Mere info',
|
||||
pasteURL: 'Indsæt URL',
|
||||
previewSizes: 'Forhåndsvisningsstørrelser',
|
||||
selectCollectionToBrowse: 'Vælg en samling for at browse',
|
||||
selectFile: 'Vælg en fil',
|
||||
setCropArea: 'Indstil beskæringsområde',
|
||||
setFocalPoint: 'Indstil fokuspunkt',
|
||||
sizes: 'Størrelse',
|
||||
sizesFor: 'Størrelse for {{label}}',
|
||||
width: 'Bredde',
|
||||
},
|
||||
validation: {
|
||||
emailAddress: 'Indtast venligst en gyldig e-mailadresse.',
|
||||
enterNumber: 'Indtast venligst et gyldigt nummer.',
|
||||
fieldHasNo: 'Dette felt har ingen {{label}}',
|
||||
greaterThanMax: '{{value}} er større end det maksimalt tilladte {{label}} of {{max}}.',
|
||||
invalidInput: 'Dette felt har et ugyldigt indtastning.',
|
||||
invalidSelection: 'Dette felt har en ugyldig valg.',
|
||||
invalidSelections: 'Dette felt har følgende ugyldige valg:',
|
||||
lessThanMin: '{{value}} er mindre end den minimum tilladte {{label}} of {{min}}.',
|
||||
limitReached: 'Grænse nået, kun {{max}} elementer kan tilføjes.',
|
||||
longerThanMin: 'Denne værdi skal være længere end den minimale længde på {{minLength}} tegn.',
|
||||
notValidDate: '"{{value}}" er ikke en gyldig dato.',
|
||||
required: 'Dette felt er påkrævet.',
|
||||
requiresAtLeast: 'Dette felt kræver mindst {{count}} {{label}}.',
|
||||
requiresNoMoreThan: 'Dette felt kræver maks {{count}} {{label}}.',
|
||||
requiresTwoNumbers: 'Dette felt kræver to numre.',
|
||||
shorterThanMax: 'Denne værdi skal være kortere end den maksimale længde af {{maxLength}} tegn.',
|
||||
trueOrFalse: 'Denne værdi kan kun være lig med sandt eller falsk.',
|
||||
username:
|
||||
'Indtast et brugernavn. Kan indeholde bogstaver, tal, bindestreger, punktum og underscores.',
|
||||
validUploadID: 'Dette felt er ikke en gyldig upload-ID.',
|
||||
},
|
||||
version: {
|
||||
type: 'Type',
|
||||
aboutToPublishSelection:
|
||||
'Du er ved at offentliggøre alt {{label}} i denne sektion. Er du sikker?',
|
||||
aboutToRestore:
|
||||
'Du er ved at gendanne dette {{label}} dokument til den tilstand, det var i den {{versionDate}}.',
|
||||
aboutToRestoreGlobal:
|
||||
'Du er ved at gendanne den globale {{label}} til den tilstand, den var i den {{versionDate}}.',
|
||||
aboutToRevertToPublished:
|
||||
'Du er ved at tilbagerulle dette dokuments ændringer til dets offentliggjorte tilstand. Er du sikker?',
|
||||
aboutToUnpublish: 'Du er ved at afpublicere dette dokument. Er du sikker?',
|
||||
aboutToUnpublishSelection:
|
||||
'Du er ved at afpublicere alt {{label}} i denne sektion. Er du sikker?',
|
||||
autosave: 'Autosave',
|
||||
autosavedSuccessfully: 'Autosaved gennemført.',
|
||||
autosavedVersion: 'Autosaved version',
|
||||
changed: 'Ændret',
|
||||
compareVersion: 'Sammenlign version med:',
|
||||
confirmPublish: 'Bekræft offentliggørelse',
|
||||
confirmRevertToSaved: 'Bekræft tilbagerulning til gemt',
|
||||
confirmUnpublish: 'Bekræft afpublicering',
|
||||
confirmVersionRestoration: 'Bekræft versionens gendannelse',
|
||||
currentDocumentStatus: 'Nuværende {{docStatus}} dokument',
|
||||
currentDraft: 'Nuværende kladde',
|
||||
currentPublishedVersion: 'Nuværende offentliggjort version',
|
||||
draft: 'Kladde',
|
||||
draftSavedSuccessfully: 'Kladde gemt.',
|
||||
lastSavedAgo: 'Sidst gemt {{distance}}',
|
||||
noFurtherVersionsFound: 'Ingen yderligere versioner fundet',
|
||||
noRowsFound: 'Ingen {{label}} fundet',
|
||||
noRowsSelected: 'Ingen {{label}} valgt',
|
||||
preview: 'Forhåndsvisning',
|
||||
previouslyPublished: 'Tidligere offentliggjort',
|
||||
problemRestoringVersion: 'Der opstod et problem med at gendanne denne version',
|
||||
publish: 'Offentliggør',
|
||||
publishChanges: 'Offentliggør ændringer',
|
||||
published: 'Offentliggjort',
|
||||
publishIn: 'Offentliggør i',
|
||||
publishing: 'Offentliggør',
|
||||
restoreAsDraft: 'Gendan som kladde',
|
||||
restoredSuccessfully: 'Gendannet.',
|
||||
restoreThisVersion: 'Gendan denne version',
|
||||
restoring: 'Gendanner...',
|
||||
reverting: 'Tilbageruller...',
|
||||
revertToPublished: 'Tilbagerul til offentliggjort',
|
||||
saveDraft: 'Gem kladde',
|
||||
selectLocales: 'Vælg lokaliteter, der skal vises',
|
||||
selectVersionToCompare: 'Vælg en version til sammenligning',
|
||||
showingVersionsFor: 'Viser versioner for:',
|
||||
showLocales: 'Vis lokaliteter:',
|
||||
status: 'Status',
|
||||
unpublish: 'Afpublicer',
|
||||
unpublishing: 'Afpublicerer...',
|
||||
version: 'Version',
|
||||
versionCount_many: '{{count}} versioner fundet',
|
||||
versionCount_none: 'Ingen versioner fundet',
|
||||
versionCount_one: '{{count}} version fundet',
|
||||
versionCount_other: '{{count}} version fundet',
|
||||
versionCreatedOn: '{{version}} oprettet den:',
|
||||
versionID: 'Versions-ID',
|
||||
versions: 'Versioner',
|
||||
viewingVersion: 'Se versionen for {{entityLabel}} {{documentTitle}}',
|
||||
viewingVersionGlobal: 'Se version for det globale {{entityLabel}}',
|
||||
viewingVersions: 'Se versioner for {{entityLabel}} {{documentTitle}}',
|
||||
viewingVersionsGlobal: 'Se versioner for det global {{entityLabel}}',
|
||||
},
|
||||
}
|
||||
|
||||
export const da: Language = {
|
||||
dateFNSKey: 'da',
|
||||
translations: daTranslations,
|
||||
}
|
||||
@@ -3,30 +3,30 @@ import type { DefaultTranslationsObject, Language } from '../types.js'
|
||||
export const hrTranslations: DefaultTranslationsObject = {
|
||||
authentication: {
|
||||
account: 'Račun',
|
||||
accountOfCurrentUser: 'Račun od trenutnog korisnika',
|
||||
accountOfCurrentUser: 'Račun trenutnog korisnika',
|
||||
accountVerified: 'Račun je uspješno verificiran.',
|
||||
alreadyActivated: 'Već aktivirano',
|
||||
alreadyLoggedIn: 'Već prijavljen',
|
||||
alreadyLoggedIn: 'Već prijavljeni',
|
||||
apiKey: 'API ključ',
|
||||
authenticated: 'Autenticiran',
|
||||
backToLogin: 'Nazad na prijavu',
|
||||
beginCreateFirstUser: 'Za početak, kreiraj svog prvog korisnika.',
|
||||
changePassword: 'Promjeni lozinku',
|
||||
backToLogin: 'Natrag na prijavu',
|
||||
beginCreateFirstUser: 'Za početak, izradite prvog korisnika.',
|
||||
changePassword: 'Promijeni lozinku',
|
||||
checkYourEmailForPasswordReset:
|
||||
'Provjerite email s poveznicom koja će Vam omogućiti sigurnu promjenu lozinke.',
|
||||
confirmGeneration: 'Potvrdi kreiranje',
|
||||
'Provjerite e-mail s poveznicom koja će Vam omogućiti sigurnu promjenu lozinke.',
|
||||
confirmGeneration: 'Potvrdi generiranje',
|
||||
confirmPassword: 'Potvrdi lozinku',
|
||||
createFirstUser: 'Kreiraj prvog korisnika',
|
||||
emailNotValid: 'Email nije ispravan',
|
||||
emailOrUsername: 'E-mail ili Korisničko ime',
|
||||
emailSent: 'Email poslan',
|
||||
emailVerified: 'Email uspješno provjeren.',
|
||||
createFirstUser: 'Izradi prvog korisnika',
|
||||
emailNotValid: 'E-mail nije ispravan',
|
||||
emailOrUsername: 'E-mail ili korisničko ime',
|
||||
emailSent: 'E-mail poslan',
|
||||
emailVerified: 'E-mail uspješno verificiran.',
|
||||
enableAPIKey: 'Omogući API ključ',
|
||||
failedToUnlock: 'Neuspješno otključavanje.',
|
||||
failedToUnlock: 'Otključavanje nije uspjelo.',
|
||||
forceUnlock: 'Prisilno otključaj',
|
||||
forgotPassword: 'Zaboravljena lozinka',
|
||||
forgotPasswordEmailInstructions:
|
||||
'Molim unesite svoj email. Primit ćete poruku s uputama za ponovno postavljanje lozinke.',
|
||||
'Molimo unesite svoju e-mail adresu. Primit ćete poruku s uputama za ponovno postavljanje lozinke.',
|
||||
forgotPasswordQuestion: 'Zaboravljena lozinka?',
|
||||
forgotPasswordUsernameInstructions:
|
||||
'Molimo unesite vaše korisničko ime ispod. Upute o tome kako resetirati vašu lozinku bit će poslane na e-adresu povezanu s vašim korisničkim imenom.',
|
||||
@@ -34,14 +34,15 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
generateNewAPIKey: 'Generiraj novi API ključ',
|
||||
generatingNewAPIKeyWillInvalidate:
|
||||
'Generiranje novog API ključa će <1>poništiti</1> prethodni ključ. Jeste li sigurni da želite nastaviti?',
|
||||
newAPIKeyGenerated: 'New API ključ generiran.',
|
||||
lockUntil: 'Zaključaj dok',
|
||||
logBackIn: 'Ponovna prijava',
|
||||
logBackIn: 'Ponovno se prijavite',
|
||||
loggedIn: 'Za prijavu s drugim korisničkim računom potrebno je prvo <0>odjaviti se</0>',
|
||||
loggedInChangePassword:
|
||||
'Da biste promijenili lozinku, otvorite svoj <0>račun</0> i promijenite lozinku tamo.',
|
||||
loggedOutInactivity: 'Odjavljeni se zbog neaktivnosti.',
|
||||
loggedOutSuccessfully: 'Uspješno ste odjavljeni..',
|
||||
loggingOut: 'Odjavljujem se...',
|
||||
'Da biste promijenili lozinku, otvorite svoj <0>račun</0> i promijenite je tamo.',
|
||||
loggedOutInactivity: 'Odjavljeni ste zbog neaktivnosti.',
|
||||
loggedOutSuccessfully: 'Uspješno ste odjavljeni.',
|
||||
loggingOut: 'Odjava u tijeku...',
|
||||
login: 'Prijava',
|
||||
loginAttempts: 'Pokušaji prijave',
|
||||
loginUser: 'Prijava korisnika',
|
||||
@@ -52,16 +53,15 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
logoutSuccessful: 'Odjava uspješna.',
|
||||
logoutUser: 'Odjava korisnika',
|
||||
newAccountCreated:
|
||||
'Novi račun je kreiran. Pristupite računu klikom na <a href="{{serverURL}}">{{serverURL}}</a>. Molim kliknite na sljedeći link ili zalijepite URL, koji se nalazi ispod, u preglednik da biste potvrdili svoj email: <a href="{{verificationURL}}">{{verificationURL}}</a><br> Nakon što potvrdite email, moći ćete se prijaviti.',
|
||||
newAPIKeyGenerated: 'Novi API ključ generiran.',
|
||||
'Novi račun je izrađen. Pristupite računu klikom na: <a href="{{serverURL}}">{{serverURL}}</a>. Molimo kliknite na sljedeću poveznicu ili zalijepite URL, koji se nalazi ispod, u preglednik da biste potvrdili svoju e-mail adresu: <a href="{{verificationURL}}">{{verificationURL}}</a><br> Nakon što potvrdite e-mail adresu, moći ćete se prijaviti.',
|
||||
newPassword: 'Nova lozinka',
|
||||
passed: 'Autentifikacija je prošla',
|
||||
passwordResetSuccessfully: 'Lozinka uspješno resetirana.',
|
||||
resetPassword: 'Restartiranje lozinke',
|
||||
resetPasswordExpiration: 'Restartiranje roka trajanja lozinke',
|
||||
resetPasswordToken: 'Restartiranje lozinke tokena',
|
||||
resetYourPassword: 'Restartiraj svoju lozinku',
|
||||
stayLoggedIn: 'Ostani prijavljen',
|
||||
resetPassword: 'Resetiranje lozinke',
|
||||
resetPasswordExpiration: 'Rok trajanja resetiranja lozinke',
|
||||
resetPasswordToken: 'Resetiranje tokena lozinke',
|
||||
resetYourPassword: 'Resetirajte svoju lozinku',
|
||||
stayLoggedIn: 'Ostanite prijavljeni',
|
||||
successfullyRegisteredFirstUser: 'Uspješno registriran prvi korisnik.',
|
||||
successfullyUnlocked: 'Uspješno otključano',
|
||||
tokenRefreshSuccessful: 'Osvježavanje tokena uspješno.',
|
||||
@@ -72,32 +72,32 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
verifiedSuccessfully: 'Uspješno potvrđeno',
|
||||
verify: 'Potvrdi',
|
||||
verifyUser: 'Potvrdi korisnika',
|
||||
verifyYourEmail: 'Potvrdi svoj email',
|
||||
verifyYourEmail: 'Potvrdi svoju e-mail adresu',
|
||||
youAreInactive:
|
||||
'Neaktivni ste neko vrijeme i uskoro ćete biti automatski odjavljeni zbog vlastite sigurnosti. Želite li ostati prijavljeni?',
|
||||
'Neaktivni ste već neko vrijeme i uskoro ćete biti automatski odjavljeni zbog vlastite sigurnosti. Želite li ostati prijavljeni?',
|
||||
youAreReceivingResetPassword:
|
||||
'Primili ste ovo jer ste Vi (ili netko drugi) zatražili promjenu lozinke za Vaš račun. Molim kliknite na poveznicu ili zalijepite ovo u svoje preglednik da biste završili proces:',
|
||||
'Primili ste ovo jer ste Vi (ili netko drugi) zatražili promjenu lozinke za Vaš račun. Molimo kliknite na poveznicu ili zalijepite ovo u svoje preglednik da biste završili proces:',
|
||||
youDidNotRequestPassword:
|
||||
'Ako niste zatražili ovo, molim ignorirajte ovaj email i Vaša lozinka ostat će nepromijenjena.',
|
||||
'Ako niste zatražili ovo, molimo ignorirajte ovaj e-mail i Vaša će lozinka ostati nepromijenjena.',
|
||||
},
|
||||
error: {
|
||||
accountAlreadyActivated: 'Ovaj račun je već aktiviran.',
|
||||
autosaving: 'Nastao je problem pri automatskom spremanju ovog dokumenta.',
|
||||
correctInvalidFields: 'Molim ispravite nevaljana polja.',
|
||||
correctInvalidFields: 'Molimo ispravite neispravna polja.',
|
||||
deletingFile: 'Dogodila se pogreška pri brisanju datoteke.',
|
||||
deletingTitle:
|
||||
'Dogodila se pogreška pri brisanju {{title}}. Molim provjerite svoju internetsku vezu i pokušajte ponovno.',
|
||||
emailOrPasswordIncorrect: 'Email ili lozinka netočni.',
|
||||
followingFieldsInvalid_one: ' Ovo polje je nevaljano:',
|
||||
followingFieldsInvalid_other: 'Ova polja su nevaljana:',
|
||||
incorrectCollection: 'Nevaljana kolekcija',
|
||||
invalidFileType: 'Nevaljan tip datoteke',
|
||||
invalidFileTypeValue: 'Nevaljan tip datoteke: {{value}}',
|
||||
loadingDocument: 'Pojavio se problem pri učitavanju dokumenta čiji je ID {{id}}.',
|
||||
'Dogodila se pogreška pri brisanju {{title}}. Molimo provjerite svoju internet vezu i pokušajte ponovno.',
|
||||
emailOrPasswordIncorrect: 'E-mail adresa ili lozinka netočni.',
|
||||
followingFieldsInvalid_one: 'Ovo polje je neispravno:',
|
||||
followingFieldsInvalid_other: 'Ova polja su neispravna:',
|
||||
incorrectCollection: 'Neispravna kolekcija',
|
||||
invalidFileType: 'Neispravan tip datoteke',
|
||||
invalidFileTypeValue: 'Neispravan tip datoteke: {{value}}',
|
||||
loadingDocument: 'Došlo je do problema pri učitavanju dokumenta čiji je ID {{id}}.',
|
||||
localesNotSaved_one: 'Sljedeću lokalnu postavku nije bilo moguće spremiti:',
|
||||
localesNotSaved_other: 'Sljedeće lokalne postavke nije bilo moguće spremiti:',
|
||||
logoutFailed: 'Odjava nije uspjela.',
|
||||
missingEmail: 'Nedostaje email.',
|
||||
missingEmail: 'Nedostaje e-mail.',
|
||||
missingIDOfDocument: 'Nedostaje ID dokumenta da bi se ažurirao.',
|
||||
missingIDOfVersion: 'Nedostaje ID verzije.',
|
||||
missingRequiredData: 'Nedostaju obvezni podaci.',
|
||||
@@ -107,22 +107,22 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
notAllowedToPerformAction: 'Nemate dopuštenje izvršiti ovu radnju.',
|
||||
notFound: 'Traženi resurs nije pronađen.',
|
||||
noUser: 'Nema korisnika',
|
||||
previewing: 'Pojavio se problem pri pregledavanju ovog dokumenta.',
|
||||
problemUploadingFile: 'Pojavio se problem pri učitavanju datoteke.',
|
||||
tokenInvalidOrExpired: 'Token je nevaljan ili je istekao.',
|
||||
previewing: 'Došlo je do problema pri pregledavanju ovog dokumenta.',
|
||||
problemUploadingFile: 'Došlo je do problema pri učitavanju datoteke.',
|
||||
tokenInvalidOrExpired: 'Token je neispravan ili je istekao.',
|
||||
tokenNotProvided: 'Token nije pružen.',
|
||||
unPublishingDocument: 'Došlo je do problema pri poništavanju objave ovog dokumenta.',
|
||||
unableToDeleteCount: 'Nije moguće izbrisati {{count}} od {{total}} {{label}}.',
|
||||
unableToUpdateCount: 'Nije moguće ažurirati {{count}} od {{total}} {{label}}.',
|
||||
unauthorized: 'Neovlašten, morate biti prijavljeni da biste uputili ovaj zahtjev.',
|
||||
unauthorized: 'Neovlašteno, morate biti prijavljeni da biste uputili ovaj zahtjev.',
|
||||
unknown: 'Došlo je do nepoznate pogreške.',
|
||||
unPublishingDocument: 'Pojavio se problem pri poništavanju objave ovog dokumenta.',
|
||||
unspecific: 'Došlo je do pogreške.',
|
||||
userEmailAlreadyRegistered: 'Korisnik s navedenom e-poštom je već registriran.',
|
||||
userEmailAlreadyRegistered: 'Korisnik s navedenom e-mail adresom je već registriran.',
|
||||
userLocked: 'Ovaj korisnik je zaključan zbog previše neuspješnih pokušaja prijave.',
|
||||
usernameAlreadyRegistered: 'Korisnik s navedenim korisničkim imenom već je registriran.',
|
||||
usernameOrPasswordIncorrect: 'Korisničko ime ili lozinka koju ste unijeli su netočni.',
|
||||
valueMustBeUnique: 'Vrijednost mora biti jedinstvena.',
|
||||
verificationTokenInvalid: 'Verifikacijski token je nevaljan.',
|
||||
verificationTokenInvalid: 'Verifikacijski token je neispravan.',
|
||||
},
|
||||
fields: {
|
||||
addLabel: 'Dodaj {{label}}',
|
||||
@@ -149,7 +149,7 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
itemsAndMore: '{{items}} i {{count}} više',
|
||||
labelRelationship: '{{label}} veza',
|
||||
latitude: 'Zemljopisna širina',
|
||||
linkedTo: 'Povezabi sa <0>{{label}}</0>',
|
||||
linkedTo: 'Povezan s <0>{{label}}</0>',
|
||||
linkType: 'Tip poveznce',
|
||||
longitude: 'Zemljopisna dužina',
|
||||
newLabel: 'Novo {{label}}',
|
||||
@@ -161,7 +161,7 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
removeUpload: 'Ukloni prijenos',
|
||||
saveChanges: 'Spremi promjene',
|
||||
searchForBlock: 'Potraži blok',
|
||||
selectExistingLabel: 'Odaberi postojeće{{label}}',
|
||||
selectExistingLabel: 'Odaberi postojeće {{label}}',
|
||||
selectFieldsToEdit: 'Odaberite polja za uređivanje',
|
||||
showAll: 'Pokaži sve',
|
||||
swapRelationship: 'Zamijeni vezu',
|
||||
@@ -178,7 +178,7 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
addBelow: 'Dodaj ispod',
|
||||
addFilter: 'Dodaj filter',
|
||||
adminTheme: 'Administratorska tema',
|
||||
and: 'I',
|
||||
and: 'i',
|
||||
anotherUserTakenOver: 'Drugi korisnik je preuzeo uređivanje ovog dokumenta.',
|
||||
applyChanges: 'Primijeni promjene',
|
||||
ascending: 'Uzlazno',
|
||||
@@ -197,21 +197,21 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
confirmDuplication: 'Potvrdi duplikaciju',
|
||||
copied: 'Kopirano',
|
||||
copy: 'Kopiraj',
|
||||
create: 'Kreiraj',
|
||||
create: 'Izradi',
|
||||
created: 'Kreirano',
|
||||
createdAt: 'Kreirano u',
|
||||
createNew: 'Kreiraj novo',
|
||||
createNewLabel: 'Kreiraj novo {{label}}',
|
||||
creating: 'Kreira se',
|
||||
creatingNewLabel: 'Kreiranje novog {{label}}',
|
||||
createdAt: 'Izrađeno u',
|
||||
createNew: 'Izradi novo',
|
||||
createNewLabel: 'Izradi novo {{label}}',
|
||||
creating: 'U izradi',
|
||||
creatingNewLabel: 'Izrađivanje novog {{label}}',
|
||||
currentlyEditing:
|
||||
'trenutno uređuje ovaj dokument. Ako preuzmete, bit će im onemogućeno daljnje uređivanje i mogu izgubiti nespremljene promjene.',
|
||||
custom: 'Prilagođen',
|
||||
dark: 'Tamno',
|
||||
dashboard: 'Nadzorna ploča',
|
||||
delete: 'Obriši',
|
||||
delete: 'Izbriši',
|
||||
deletedCountSuccessfully: 'Uspješno izbrisano {{count}} {{label}}.',
|
||||
deletedSuccessfully: 'Uspješno obrisano.',
|
||||
deletedSuccessfully: 'Uspješno izbrisano.',
|
||||
deleting: 'Brisanje...',
|
||||
depth: 'Dubina',
|
||||
descending: 'Silazno',
|
||||
@@ -258,17 +258,16 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
next: 'Sljedeće',
|
||||
noFiltersSet: 'Nema postavljenih filtera',
|
||||
noLabel: '<Nema {{label}}>',
|
||||
none: 'Nijedan',
|
||||
noOptions: 'Nema opcija',
|
||||
noResults:
|
||||
'Nema pronađenih {{label}}. Ili {{label}} još uvijek ne postoji ili nijedan od odgovara postavljenim filterima.',
|
||||
notFound: 'Nije pronađeno',
|
||||
nothingFound: 'Ništa nije pronađeno',
|
||||
none: 'Nijedan',
|
||||
noOptions: 'Nema opcija',
|
||||
noResults: 'Nije pronađen nijedan {{label}}. Ili {{label}} još uvijek ne postoji ili nijedan od odgovara postavljenim filterima.',
|
||||
noValue: 'Bez vrijednosti',
|
||||
of: 'Od',
|
||||
of: 'od',
|
||||
only: 'Samo',
|
||||
open: 'Otvori',
|
||||
or: 'Ili',
|
||||
or: 'ili',
|
||||
order: 'Poredak',
|
||||
pageNotFound: 'Stranica nije pronađena',
|
||||
password: 'Lozinka',
|
||||
@@ -295,11 +294,11 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
submit: 'Podnesi',
|
||||
submitting: 'Podnošenje...',
|
||||
success: 'Uspjeh',
|
||||
successfullyCreated: '{{label}} uspješno kreirano.',
|
||||
successfullyCreated: '{{label}} uspješno izrađeno.',
|
||||
successfullyDuplicated: '{{label}} uspješno duplicirano.',
|
||||
takeOver: 'Preuzmi',
|
||||
thisLanguage: 'Hrvatski',
|
||||
titleDeleted: '{{label}} "{{title}}" uspješno obrisano.',
|
||||
titleDeleted: '{{label}} "{{title}}" uspješno izbrisano.',
|
||||
true: 'Istinito',
|
||||
unauthorized: 'Neovlašteno',
|
||||
unsavedChangesDuplicate: 'Imate nespremljene promjene. Želite li nastaviti s dupliciranjem?',
|
||||
@@ -312,7 +311,7 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
user: 'Korisnik',
|
||||
username: 'Korisničko ime',
|
||||
users: 'Korisnici',
|
||||
value: 'Attribute',
|
||||
value: 'Vrijednost',
|
||||
viewReadOnly: 'Pogledaj samo za čitanje',
|
||||
welcome: 'Dobrodošli',
|
||||
},
|
||||
@@ -335,8 +334,8 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
upload: {
|
||||
addFile: 'Dodaj datoteku',
|
||||
addFiles: 'Dodaj datoteke',
|
||||
bulkUpload: 'Masovno otpremanje',
|
||||
crop: 'Usjev',
|
||||
bulkUpload: 'Masovno dodavanje',
|
||||
crop: 'Izreži',
|
||||
cropToolDescription:
|
||||
'Povucite kutove odabranog područja, nacrtajte novo područje ili prilagodite vrijednosti ispod.',
|
||||
dragAndDrop: 'Povucite i ispustite datoteku',
|
||||
@@ -363,13 +362,13 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
width: 'Širina',
|
||||
},
|
||||
validation: {
|
||||
emailAddress: 'Molim unestie valjanu email adresu.',
|
||||
enterNumber: 'Molim unesite valjani broj.',
|
||||
emailAddress: 'Molimo unesite valjanu e-mail adresu.',
|
||||
enterNumber: 'Molimo unesite valjani broj.',
|
||||
fieldHasNo: 'Ovo polje nema {{label}}',
|
||||
greaterThanMax: '{{value}} exceeds the maximum allowable {{label}} limit of {{max}}.',
|
||||
invalidInput: 'Ovo polje ima nevaljan unos.',
|
||||
invalidSelection: 'Ovo polje ima nevaljan odabir.',
|
||||
invalidSelections: 'Ovo polje ima sljedeće nevaljane odabire:',
|
||||
invalidInput: 'Ovo polje ima neispravan unos.',
|
||||
invalidSelection: 'Ovo polje ima neispravan odabir.',
|
||||
invalidSelections: 'Ovo polje ima sljedeće neispravne odabire:',
|
||||
lessThanMin: '{{value}} is below the minimum allowable {{label}} limit of {{min}}.',
|
||||
limitReached: 'Dosegnut je limit, može se dodati samo {{max}} stavki.',
|
||||
longerThanMin: 'Ova vrijednost mora biti duža od minimalne dužine od {{minLength}} znakova',
|
||||
@@ -386,14 +385,14 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
},
|
||||
version: {
|
||||
type: 'Tip',
|
||||
aboutToPublishSelection: 'Upravo ćete objaviti sve {{label}} u izboru. Jesi li siguran?',
|
||||
aboutToPublishSelection: 'Upravo ćete objaviti sve {{label}} u izboru. Jeste li sigurni?',
|
||||
aboutToRestore: 'Vratit ćete {{label}} dokument u stanje u kojem je bio {{versionDate}}',
|
||||
aboutToRestoreGlobal: 'Vratit ćete globalni {{label}} u stanje u kojem je bio {{versionDate}}.',
|
||||
aboutToRevertToPublished:
|
||||
'Vratit ćete promjene u dokumentu u objavljeno stanje. Jeste li sigurni? ',
|
||||
aboutToUnpublish: 'Poništit ćete objavu ovog dokumenta. Jeste li sigurni?',
|
||||
aboutToUnpublishSelection:
|
||||
'Upravo ćete poništiti objavu svih {{label}} u odabiru. Jesi li siguran?',
|
||||
'Upravo ćete poništiti objavu svih {{label}} u odabiru. Jeste li sigurni?',
|
||||
autosave: 'Automatsko spremanje',
|
||||
autosavedSuccessfully: 'Automatsko spremanje uspješno.',
|
||||
autosavedVersion: 'Verzija automatski spremljenog dokumenta',
|
||||
@@ -439,7 +438,7 @@ export const hrTranslations: DefaultTranslationsObject = {
|
||||
versionCount_none: 'Nema pronađenih verzija',
|
||||
versionCount_one: '{{count}} pronađena verzija',
|
||||
versionCount_other: '{{count}} pronađenih verzija',
|
||||
versionCreatedOn: '{{version}} kreiranih:',
|
||||
versionCreatedOn: '{{version}} izrađenih:',
|
||||
versionID: 'ID verzije',
|
||||
versions: 'Verzije',
|
||||
viewingVersion: 'Pregled verzije za {{entityLabel}} {{documentTitle}}',
|
||||
|
||||
@@ -9,6 +9,7 @@ type DateFNSKeys =
|
||||
| 'az'
|
||||
| 'bg'
|
||||
| 'cs'
|
||||
| 'da'
|
||||
| 'de'
|
||||
| 'en-US'
|
||||
| 'es'
|
||||
|
||||
@@ -7,6 +7,7 @@ export const acceptedLanguages = [
|
||||
'az',
|
||||
'bg',
|
||||
'cs',
|
||||
'da',
|
||||
'de',
|
||||
'en',
|
||||
'es',
|
||||
@@ -51,7 +52,6 @@ export const acceptedLanguages = [
|
||||
* 'ca',
|
||||
* 'ca-ES-valencia',
|
||||
* 'cy',
|
||||
* 'da',
|
||||
* 'el',
|
||||
* 'en-GB',
|
||||
* 'en-US',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/ui",
|
||||
"version": "3.0.0-beta.109",
|
||||
"version": "3.0.0-beta.110",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -63,7 +63,12 @@ export type ReactSelectAdapterProps = {
|
||||
disabled?: boolean
|
||||
filterOption?:
|
||||
| ((
|
||||
{ data, label, value }: { data: Option; label: string; value: string },
|
||||
{
|
||||
allowEdit,
|
||||
data,
|
||||
label,
|
||||
value,
|
||||
}: { allowEdit: boolean; data: Option; label: string; value: string },
|
||||
search: string,
|
||||
) => boolean)
|
||||
| undefined
|
||||
|
||||
@@ -28,12 +28,12 @@ export const TableCellProvider: React.FC<{
|
||||
return (
|
||||
<TableCellContext.Provider
|
||||
value={{
|
||||
...contextToInherit,
|
||||
cellData,
|
||||
cellProps,
|
||||
columnIndex,
|
||||
customCellContext,
|
||||
rowData,
|
||||
...contextToInherit,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -3,11 +3,12 @@ import type { Option } from '../../elements/ReactSelect/types.js'
|
||||
import type { OptionGroup, Value } from './types.js'
|
||||
|
||||
type Args = {
|
||||
allowEdit: boolean
|
||||
options: OptionGroup[]
|
||||
value: Value | Value[]
|
||||
}
|
||||
|
||||
export const findOptionsByValue = ({ options, value }: Args): Option | Option[] => {
|
||||
export const findOptionsByValue = ({ allowEdit, options, value }: Args): Option | Option[] => {
|
||||
if (value || typeof value === 'number') {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((val) => {
|
||||
@@ -25,7 +26,7 @@ export const findOptionsByValue = ({ options, value }: Args): Option | Option[]
|
||||
}
|
||||
})
|
||||
|
||||
return matchedOption
|
||||
return matchedOption ? { allowEdit, ...matchedOption } : undefined
|
||||
})
|
||||
}
|
||||
|
||||
@@ -42,7 +43,7 @@ export const findOptionsByValue = ({ options, value }: Args): Option | Option[]
|
||||
}
|
||||
})
|
||||
|
||||
return matchedOption
|
||||
return matchedOption ? { allowEdit, ...matchedOption } : undefined
|
||||
}
|
||||
|
||||
return undefined
|
||||
|
||||
@@ -46,6 +46,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
_path: pathFromProps,
|
||||
admin: {
|
||||
allowCreate = true,
|
||||
allowEdit = true,
|
||||
className,
|
||||
description,
|
||||
isSortable = true,
|
||||
@@ -576,7 +577,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
}
|
||||
}, [openDrawer, currentlyOpenRelationship])
|
||||
|
||||
const valueToRender = findOptionsByValue({ options, value })
|
||||
const valueToRender = findOptionsByValue({ allowEdit, options, value })
|
||||
|
||||
if (!Array.isArray(valueToRender) && valueToRender?.value === 'null') {
|
||||
valueToRender.value = null
|
||||
|
||||
@@ -24,7 +24,7 @@ export const MultiValueLabel: React.FC<
|
||||
} & MultiValueProps<Option>
|
||||
> = (props) => {
|
||||
const {
|
||||
data: { label, relationTo, value },
|
||||
data: { allowEdit, label, relationTo, value },
|
||||
selectProps: { customProps: { draggableProps, onDocumentDrawerOpen } = {} } = {},
|
||||
} = props
|
||||
|
||||
@@ -44,7 +44,7 @@ export const MultiValueLabel: React.FC<
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{relationTo && hasReadPermission && (
|
||||
{relationTo && hasReadPermission && allowEdit !== false && (
|
||||
<Fragment>
|
||||
<button
|
||||
aria-label={`Edit ${label}`}
|
||||
|
||||
@@ -25,7 +25,7 @@ export const SingleValue: React.FC<
|
||||
> = (props) => {
|
||||
const {
|
||||
children,
|
||||
data: { label, relationTo, value },
|
||||
data: { allowEdit, label, relationTo, value },
|
||||
selectProps: { customProps: { onDocumentDrawerOpen } = {} } = {},
|
||||
} = props
|
||||
|
||||
@@ -39,7 +39,7 @@ export const SingleValue: React.FC<
|
||||
<div className={`${baseClass}__label`}>
|
||||
<div className={`${baseClass}__label-text`}>
|
||||
<div className={`${baseClass}__text`}>{children}</div>
|
||||
{relationTo && hasReadPermission && (
|
||||
{relationTo && hasReadPermission && allowEdit !== false && (
|
||||
<Fragment>
|
||||
<button
|
||||
aria-label={t('general:editLabel', { label })}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { I18nClient } from '@payloadcms/translations'
|
||||
import type { ClientCollectionConfig, ClientConfig, FilterOptionsResult } from 'payload'
|
||||
|
||||
export type Option = {
|
||||
allowEdit: boolean
|
||||
label: string
|
||||
options?: Option[]
|
||||
relationTo?: string
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useFieldProps } from '../../forms/FieldPropsProvider/index.js'
|
||||
import { useField } from '../../forms/useField/index.js'
|
||||
import { withCondition } from '../../forms/withCondition/index.js'
|
||||
import { useConfig } from '../../providers/Config/index.js'
|
||||
import { useLocale } from '../../providers/Locale/index.js'
|
||||
import { useTranslation } from '../../providers/Translation/index.js'
|
||||
import { isFieldRTL } from '../shared/index.js'
|
||||
import './index.scss'
|
||||
@@ -42,7 +43,6 @@ const TextareaFieldComponent: TextareaFieldClientComponent = (props) => {
|
||||
required,
|
||||
},
|
||||
labelProps,
|
||||
locale,
|
||||
readOnly: readOnlyFromTopLevelProps,
|
||||
validate,
|
||||
} = props
|
||||
@@ -50,6 +50,7 @@ const TextareaFieldComponent: TextareaFieldClientComponent = (props) => {
|
||||
const readOnlyFromProps = readOnlyFromTopLevelProps || readOnlyFromAdmin
|
||||
|
||||
const { i18n } = useTranslation()
|
||||
const locale = useLocale()
|
||||
|
||||
const {
|
||||
config: { localization },
|
||||
|
||||
@@ -153,6 +153,9 @@ export function UploadInput(props: UploadInputProps) {
|
||||
collectionSlug: activeRelationTo,
|
||||
})
|
||||
|
||||
/**
|
||||
* Prevent initial retrieval of documents from running more than once
|
||||
*/
|
||||
const loadedValueDocsRef = React.useRef<boolean>(false)
|
||||
|
||||
const canCreate = useMemo(() => {
|
||||
@@ -388,6 +391,7 @@ export function UploadInput(props: UploadInputProps) {
|
||||
useEffect(() => {
|
||||
async function loadInitialDocs() {
|
||||
if (value) {
|
||||
loadedValueDocsRef.current = true
|
||||
const loadedDocs = await populateDocs(
|
||||
Array.isArray(value) ? value : [value],
|
||||
activeRelationTo,
|
||||
@@ -398,8 +402,6 @@ export function UploadInput(props: UploadInputProps) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
loadedValueDocsRef.current = true
|
||||
}
|
||||
|
||||
if (!loadedValueDocsRef.current) {
|
||||
|
||||
@@ -389,7 +389,10 @@ const DocumentInfo: React.FC<
|
||||
|
||||
if (docAccessURL) {
|
||||
const res = await fetch(`${serverURL}${api}${docAccessURL}?${qs.stringify(params)}`, {
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify({
|
||||
...(data || {}),
|
||||
_status: 'draft',
|
||||
}),
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept-Language': i18n.language,
|
||||
|
||||
@@ -1,11 +1,2 @@
|
||||
'use client'
|
||||
import * as facelessUIImport from '@faceless-ui/scroll-info'
|
||||
const { ScrollInfoProvider } =
|
||||
facelessUIImport && 'ScrollInfoProvider' in facelessUIImport
|
||||
? facelessUIImport
|
||||
: { ScrollInfoProvider: undefined }
|
||||
const { useScrollInfo } =
|
||||
facelessUIImport && 'useScrollInfo' in facelessUIImport
|
||||
? facelessUIImport
|
||||
: { useScrollInfo: undefined }
|
||||
export { ScrollInfoProvider, useScrollInfo }
|
||||
export { ScrollInfoProvider, useScrollInfo } from '@faceless-ui/scroll-info'
|
||||
|
||||
354
pnpm-lock.yaml
generated
354
pnpm-lock.yaml
generated
@@ -1229,35 +1229,35 @@ importers:
|
||||
specifier: 2.0.0-beta.0
|
||||
version: 2.0.0-beta.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)
|
||||
'@lexical/headless':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/link':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/list':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/mark':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/markdown':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/react':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)(yjs@13.6.18)
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)(yjs@13.6.18)
|
||||
'@lexical/rich-text':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/selection':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/table':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/utils':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@payloadcms/next':
|
||||
specifier: workspace:*
|
||||
version: link:../next
|
||||
@@ -1280,8 +1280,8 @@ importers:
|
||||
specifier: 1.0.3
|
||||
version: 1.0.3
|
||||
lexical:
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
react:
|
||||
specifier: 19.0.0-rc-5dcb0097-20240918
|
||||
version: 19.0.0-rc-5dcb0097-20240918
|
||||
@@ -1311,8 +1311,8 @@ importers:
|
||||
specifier: ^7.24.1
|
||||
version: 7.24.7(@babel/core@7.25.2)
|
||||
'@lexical/eslint-plugin':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0(eslint@9.9.1(jiti@1.21.6))
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0(eslint@9.9.1(jiti@1.21.6))
|
||||
'@payloadcms/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:../eslint-config
|
||||
@@ -1643,11 +1643,11 @@ importers:
|
||||
specifier: ^3.614.0
|
||||
version: 3.629.0
|
||||
'@lexical/headless':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@lexical/markdown':
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
'@payloadcms/db-mongodb':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/db-mongodb
|
||||
@@ -1781,8 +1781,8 @@ importers:
|
||||
specifier: 4.0.0
|
||||
version: 4.0.0
|
||||
lexical:
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
specifier: 0.18.0
|
||||
version: 0.18.0
|
||||
next:
|
||||
specifier: 15.0.0-canary.160
|
||||
version: 15.0.0-canary.160(@playwright/test@1.46.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@0.0.0-experimental-24ec0eb-20240918)(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)(sass@1.77.4)
|
||||
@@ -3594,82 +3594,82 @@ packages:
|
||||
'@juggle/resize-observer@3.4.0':
|
||||
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
||||
|
||||
'@lexical/clipboard@0.17.0':
|
||||
resolution: {integrity: sha512-wYtC6VJhuSxUZc69VTU+vBgzB4HQqhve2hLrr3v+3tR2aimx3KnKphCCP1TexCntxpEnOTPXafEgpOW/EVQE+Q==}
|
||||
'@lexical/clipboard@0.18.0':
|
||||
resolution: {integrity: sha512-ybc+hx14wj0n2ZjdOkLcZ02MRB3UprXjpLDXlByFIuVcZpUxVcp3NzA0UBPOKXYKvdt0bmgjnAsFWM5OSbwS0w==}
|
||||
|
||||
'@lexical/code@0.17.0':
|
||||
resolution: {integrity: sha512-8zrgHzf27aYySfUVeSKw8YP/LkRlXHSwD03BKlkSZAb4HX/WC60SGmdXUhtyTIBucqe0pnuGsRYfR9euD0/tfw==}
|
||||
'@lexical/code@0.18.0':
|
||||
resolution: {integrity: sha512-VB8fRHIrB8QTqyZUvGBMVWP2tpKe3ArOjPdWAqgrS8MVFldqUhuTHcW+XJFkVxcEBYCXynNT29YRYtQhfQ+vDQ==}
|
||||
|
||||
'@lexical/devtools-core@0.17.0':
|
||||
resolution: {integrity: sha512-0ftqWsoCb96oTc8Ok+uvjGAXZpsN9oc6ml3d46BdufdZyxHXC4qU3YVoPfLkgAHzH+4fQlNypu7u3Ym3dZ2rJg==}
|
||||
'@lexical/devtools-core@0.18.0':
|
||||
resolution: {integrity: sha512-gVgtEkLwGjz1frOmDpFJzDPFxPgAcC9n5ZaaZWHo5GLcptnQmkuLm1t+UInQWujXhFmcyJzfiqDaMJ8EIcb2Ww==}
|
||||
peerDependencies:
|
||||
react: 19.0.0-rc-5dcb0097-20240918
|
||||
react-dom: 19.0.0-rc-5dcb0097-20240918
|
||||
|
||||
'@lexical/dragon@0.17.0':
|
||||
resolution: {integrity: sha512-XSsrHVwhjBIVF9VN9MFm6Go8fquj5H/jlYuyNzemHq0tOli8NaoSovGc5q0LwXr88RPsuIt1jluazR7Q1+kxTQ==}
|
||||
'@lexical/dragon@0.18.0':
|
||||
resolution: {integrity: sha512-toD/y2/TgtG+eFVKXf65kDk/Mv02FwgmcGH18nyAabZnO1TLBaMYPkGFdTTZ8hVmQxqIu9nZuLWUbdIBMs8UWw==}
|
||||
|
||||
'@lexical/eslint-plugin@0.17.0':
|
||||
resolution: {integrity: sha512-O6RyQBXAdi90jlthWwfOuxYG4zqzWkpNwsX1V6N8t5iH80Te04LsnfG+hIB/5V8rxm8WPkTjMrqAX3UEZy5Shg==}
|
||||
'@lexical/eslint-plugin@0.18.0':
|
||||
resolution: {integrity: sha512-i9tveFKOq6Bk5CFt7qoPJlxG16bbLApxfXevvs+PDfxiNCCTkcV/DB85rGAs6LMM0FMyEbIYbmaWpq0wOZ3FSA==}
|
||||
peerDependencies:
|
||||
eslint: '>=7.31.0 || ^8.0.0'
|
||||
|
||||
'@lexical/hashtag@0.17.0':
|
||||
resolution: {integrity: sha512-E6nSoz9haB6JypQtYxG5OYr36AHgam/FBMu77OWNl1KsJbkP8nInm+P22QFsNnEvs4Hk6/0FJ5g42+lTEnGmIg==}
|
||||
'@lexical/hashtag@0.18.0':
|
||||
resolution: {integrity: sha512-bm+Sv7keguVYbUY0ngd+iAv2Owd3dePzdVkzkmw9Al8GPXkE5ll8fjq6Xjw2u3OVhf+9pTnesIo/AS7H+h0exw==}
|
||||
|
||||
'@lexical/headless@0.17.0':
|
||||
resolution: {integrity: sha512-yKvXcq2F6S1lwDLcwv+bHht/al1LcFmidPT3rjISRxLX+/YjUcUT8MmvV773Du4piV4rFPbVlBPFBZfHJkDxXw==}
|
||||
'@lexical/headless@0.18.0':
|
||||
resolution: {integrity: sha512-GPUL7rTSYer+/g37blFbJ5MXDPCgMf1wT87Wr+IF7PdUb1D68NwePQxFBBTWMlT/wjm4YU1Qzcv5Izxldif5YQ==}
|
||||
|
||||
'@lexical/history@0.17.0':
|
||||
resolution: {integrity: sha512-SfeUKAXf9pZpqee9rMOTt33V0J0p/AS9TZLT9Un9dU6wAaHfv6NFax1ND0JoG1a9YkTc539mufxVLNjsNRc0ag==}
|
||||
'@lexical/history@0.18.0':
|
||||
resolution: {integrity: sha512-c87J4ke1Sae03coElJay2Ikac/4OcA2OmhtNbt2gAi/XBtcsP4mPuz1yZfZf9XIe+weekObgjinvZekQ2AFw0g==}
|
||||
|
||||
'@lexical/html@0.17.0':
|
||||
resolution: {integrity: sha512-sI458CEP/j+Gd2YEo1+vTax31ZAjdq5jmRJMgSKxzKlkVYAUY9eH5u3Y3awPLwLVXJHiIopMX02GeZytibuTiw==}
|
||||
'@lexical/html@0.18.0':
|
||||
resolution: {integrity: sha512-8lhba1DFnnobXgYm4Rk5Gr2tZedD4Gl6A/NKCt7whO/CET63vT3UnK2ggcVVgtIJG530Cv0bdZoJbJu5DauI5w==}
|
||||
|
||||
'@lexical/link@0.17.0':
|
||||
resolution: {integrity: sha512-Kux6yvPit6y0ksPpwimv3seVrXAsggkqB6oT6oAVBaDpYuygVEwNDqg/rCTtB3mHQ4eeuU33mdK7MSXZ34bZRQ==}
|
||||
'@lexical/link@0.18.0':
|
||||
resolution: {integrity: sha512-GCYcbNTSTwJk0lr+GMc8nn6Meq44BZs3QL2d1B0skpZAspd8yI53sRS6HDy5P+jW5P0dzyZr/XJAU4U+7zsEEg==}
|
||||
|
||||
'@lexical/list@0.17.0':
|
||||
resolution: {integrity: sha512-anDuSUykTv+lqyCwl1m+sThrB15OKCa00Eo68/d2HQSHDD3KNWgSx709dcR17bD9oT204yOhMJbQGywuzcEyGQ==}
|
||||
'@lexical/list@0.18.0':
|
||||
resolution: {integrity: sha512-DEWs9Scbg3+STZeE2O0OoG8SWnKnxQccObBzyeHRjn4GAN6JA7lgcAzfrdgp0fNWTbMM/ku876MmXKGnqhvg9Q==}
|
||||
|
||||
'@lexical/mark@0.17.0':
|
||||
resolution: {integrity: sha512-Ynqh9KHXUcB9qLOTGC9s+bbWtawOwRStkeIeAugTqrwckyYWeDaePpyJ6IhBBJy1E1CfpiZn71NDeP+FuRjnXQ==}
|
||||
'@lexical/mark@0.18.0':
|
||||
resolution: {integrity: sha512-QA4YWfTP5WWnCnoH/RmfcsSZyhhd7oeFWDpfP7S8Bbmhz6kiPwGcsVr+uRQBBT56AqEX167xX2rX8JR6FiYZqA==}
|
||||
|
||||
'@lexical/markdown@0.17.0':
|
||||
resolution: {integrity: sha512-6IuJ2l5p/Ma+VBUIStIRXwTC01GEzx21gvqqywuqBUzAOiMr1oRM+DGsQgrzZrcjX+LzUlZ5ZgjuWtK8XKVAZw==}
|
||||
'@lexical/markdown@0.18.0':
|
||||
resolution: {integrity: sha512-uSWwcK8eJw5C+waEhU5WoX8W+JxNZbKuFnZwsn5nsp+iQgqMj4qY6g0yJub4sq8vvh6jjl4vVXhXTq2up9aykw==}
|
||||
|
||||
'@lexical/offset@0.17.0':
|
||||
resolution: {integrity: sha512-onE6SD2mIAwBLTT5v5fVBVtRg/NpQj+o10vTWJ1ImvEUERpSoCyHMTy3IMoSMuCRwuOG9C0cFEret2u+QS8Icw==}
|
||||
'@lexical/offset@0.18.0':
|
||||
resolution: {integrity: sha512-KGlboyLSxQAH5PMOlJmyvHlbYXZneVnKiHpfyBV5IUX5kuyB/eZbQEYcJP9saekfQ5Xb1FWXWmsZEo+sWtrrZA==}
|
||||
|
||||
'@lexical/overflow@0.17.0':
|
||||
resolution: {integrity: sha512-dh+nQAmeobKvZFodWyzNh1ZjX043Patk/1Lwct9XmtAGMUdXL+tB0bbguWVcDfY8OYu1CTQGfbdq2oMEJYzwsg==}
|
||||
'@lexical/overflow@0.18.0':
|
||||
resolution: {integrity: sha512-3ATTwttVgZtVLq60ZUWbpbXBbpuMa3PZD5CxSP3nulviL+2I4phvacV4WUN+8wMeq+PGmuarl+cYfrFL02ii3g==}
|
||||
|
||||
'@lexical/plain-text@0.17.0':
|
||||
resolution: {integrity: sha512-AEk+3ttbRyRi7m9UbU1CdLUtGsXh4FFZkBC12twV3U82lZHOdHocLlTutP+lcbYlGjeq6UF43NxOSGzsYEunsA==}
|
||||
'@lexical/plain-text@0.18.0':
|
||||
resolution: {integrity: sha512-L6yQpiwW0ZacY1oNwvRBxSuW2TZaUcveZLheJc8JzGcZoVxzII/CAbLZG8691VbNuKsbOURiNXZIsgwujKmo4Q==}
|
||||
|
||||
'@lexical/react@0.17.0':
|
||||
resolution: {integrity: sha512-HZ3joq+5g2++2vo/6scTd60Y2bsu8ya8EUdopyudnmGZGKAcAPue9pLOlBaEpsYZ7vqTuGjiPgtEBfFzDy9rlg==}
|
||||
'@lexical/react@0.18.0':
|
||||
resolution: {integrity: sha512-DLvIbTsjvFIFqm+9zvAjEwuZHAbSxzZf1AGqf1lLctlL/Ran0f+8EZOv5jttELTe7xISZ2+xSXTLRfyxhNwGXQ==}
|
||||
peerDependencies:
|
||||
react: 19.0.0-rc-5dcb0097-20240918
|
||||
react-dom: 19.0.0-rc-5dcb0097-20240918
|
||||
|
||||
'@lexical/rich-text@0.17.0':
|
||||
resolution: {integrity: sha512-XJc8gQBSwppCkESQaNcGtyTaPXZaeCQDcUVpnDjDK0vM/ZZN8TErxbujwbSqA3kO2dBds9N8WxNboSwuncMBcQ==}
|
||||
'@lexical/rich-text@0.18.0':
|
||||
resolution: {integrity: sha512-xMANCB7WueMsmWK8qxik5FZN4ApyaHWHQILS9r4FTbdv/DlNepsR7Pt8kg2317xZ56NAueQLIdyyKYXG1nBrHw==}
|
||||
|
||||
'@lexical/selection@0.17.0':
|
||||
resolution: {integrity: sha512-UTjlvyhFY/lmHtBaIaVRwYnRfO9gR4I32+PT7vHQr4v3VfcgS63YEGSgEZy3Gh1pfeJqaZATN58+jCuMAQXlWQ==}
|
||||
'@lexical/selection@0.18.0':
|
||||
resolution: {integrity: sha512-mJoMhmxeZLfM9K2JMYETs9u179IkHQUlgtYG5GZJHjKx2iUn+9KvJ9RVssq+Lusi7C/N42wWPGNHDPdUvFtxXg==}
|
||||
|
||||
'@lexical/table@0.17.0':
|
||||
resolution: {integrity: sha512-RQF7IG0rGL2/bPaPFUIMgDA3QMdDflvXSnE7Udgbj9yMqSKhYkaERVfNyoLckDUSuusGJd6XV+qum6JWn0nSNA==}
|
||||
'@lexical/table@0.18.0':
|
||||
resolution: {integrity: sha512-TeTAnuFAAgVjm1QE8adRB3GFWN+DUUiS4vzGq+ynPRCtNdpmW27NmTkRMyxKsetUtt7nIFfj4DvLvor4RwqIpA==}
|
||||
|
||||
'@lexical/text@0.17.0':
|
||||
resolution: {integrity: sha512-kFH0V6yjW8YswmoY7vHT4zHFDflGfamuUxTPHROpdnq/JMjHeaVwtmFBdrP0gknaC8XMRXdr3EsemQ7cbOoDPA==}
|
||||
'@lexical/text@0.18.0':
|
||||
resolution: {integrity: sha512-MTHSBeq3K0+lqSsP5oysBMnY4tPVhB8kAa2xBnEc3dYgXFxEEvJwZahbHNX93EPObtJkxXfUuI63Al4G3lYK8A==}
|
||||
|
||||
'@lexical/utils@0.17.0':
|
||||
resolution: {integrity: sha512-B/n0rRGDmdMrqi2qnprLt6SntC6jb4JItLmPl8zDDdg7/HxMdLq3F93vogeiXQJn0mlNqgiENWHvLAy5K2C2uQ==}
|
||||
'@lexical/utils@0.18.0':
|
||||
resolution: {integrity: sha512-4s9dVpBZjqIaA/1q2GtfWFjKsv2Wqhjer0Zw2mcl1TIVN0zreXxcTKN316QppAWmSQJxVGvkWHjjaZJwl6/TSw==}
|
||||
|
||||
'@lexical/yjs@0.17.0':
|
||||
resolution: {integrity: sha512-xJv3frcK/jskssLbzdY4yfBaM7+LWaZD4YjYkJ/bvRDTey2w+McF+SvsJ/yBA8YF1oaL3rT+0aIQJ7rfH+AxjA==}
|
||||
'@lexical/yjs@0.18.0':
|
||||
resolution: {integrity: sha512-rl7Rl9XIb3ygQEEHOFtACdXs3BE+UUUmdyNqB6kK9A6IRGz+w4Azp+qzt8It/t+c0oaSYHpAtcLNXg1amJz+kA==}
|
||||
peerDependencies:
|
||||
yjs: '>=13.5.22'
|
||||
|
||||
@@ -7144,8 +7144,8 @@ packages:
|
||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
lexical@0.17.0:
|
||||
resolution: {integrity: sha512-cCFmANO5rIf34NF0go/hxp5S3V5Z8G2Rsa1FJy50qF2WM5EJNJ/MqN75TApjfgMkfrbO6gau3X12nCqwsT7aDg==}
|
||||
lexical@0.18.0:
|
||||
resolution: {integrity: sha512-3K/B0RpzjoW+Wj2E455wWXxkqxqK8UgdIiuqkOqdOsoSSo5mCkHOU6eVw7Nlmlr1MFvAMzGmz4RPn8NZaLQ2Mw==}
|
||||
|
||||
lib0@0.2.97:
|
||||
resolution: {integrity: sha512-Q4d1ekgvufi9FiHkkL46AhecfNjznSL9MRNoJRQ76gBHS9OqU2ArfQK0FvBpuxgWeJeNI0LVgAYMIpsGeX4gYg==}
|
||||
@@ -11999,157 +11999,159 @@ snapshots:
|
||||
|
||||
'@juggle/resize-observer@3.4.0': {}
|
||||
|
||||
'@lexical/clipboard@0.17.0':
|
||||
'@lexical/clipboard@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/html': 0.17.0
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/html': 0.18.0
|
||||
'@lexical/list': 0.18.0
|
||||
'@lexical/selection': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/code@0.17.0':
|
||||
'@lexical/code@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
prismjs: 1.29.0
|
||||
|
||||
'@lexical/devtools-core@0.17.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)':
|
||||
'@lexical/devtools-core@0.18.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)':
|
||||
dependencies:
|
||||
'@lexical/html': 0.17.0
|
||||
'@lexical/link': 0.17.0
|
||||
'@lexical/mark': 0.17.0
|
||||
'@lexical/table': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/html': 0.18.0
|
||||
'@lexical/link': 0.18.0
|
||||
'@lexical/mark': 0.18.0
|
||||
'@lexical/table': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
react: 19.0.0-rc-5dcb0097-20240918
|
||||
react-dom: 19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918)
|
||||
|
||||
'@lexical/dragon@0.17.0':
|
||||
'@lexical/dragon@0.18.0':
|
||||
dependencies:
|
||||
lexical: 0.17.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/eslint-plugin@0.17.0(eslint@9.9.1(jiti@1.21.6))':
|
||||
'@lexical/eslint-plugin@0.18.0(eslint@9.9.1(jiti@1.21.6))':
|
||||
dependencies:
|
||||
eslint: 9.9.1(jiti@1.21.6)
|
||||
|
||||
'@lexical/hashtag@0.17.0':
|
||||
'@lexical/hashtag@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/headless@0.17.0':
|
||||
'@lexical/headless@0.18.0':
|
||||
dependencies:
|
||||
lexical: 0.17.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/history@0.17.0':
|
||||
'@lexical/history@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/html@0.17.0':
|
||||
'@lexical/html@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/selection': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/link@0.17.0':
|
||||
'@lexical/link@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/list@0.17.0':
|
||||
'@lexical/list@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/mark@0.17.0':
|
||||
'@lexical/mark@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/markdown@0.17.0':
|
||||
'@lexical/markdown@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/code': 0.17.0
|
||||
'@lexical/link': 0.17.0
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/rich-text': 0.17.0
|
||||
'@lexical/text': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/code': 0.18.0
|
||||
'@lexical/link': 0.18.0
|
||||
'@lexical/list': 0.18.0
|
||||
'@lexical/rich-text': 0.18.0
|
||||
'@lexical/text': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/offset@0.17.0':
|
||||
'@lexical/offset@0.18.0':
|
||||
dependencies:
|
||||
lexical: 0.17.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/overflow@0.17.0':
|
||||
'@lexical/overflow@0.18.0':
|
||||
dependencies:
|
||||
lexical: 0.17.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/plain-text@0.17.0':
|
||||
'@lexical/plain-text@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/clipboard': 0.18.0
|
||||
'@lexical/selection': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/react@0.17.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)(yjs@13.6.18)':
|
||||
'@lexical/react@0.18.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)(yjs@13.6.18)':
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.17.0
|
||||
'@lexical/code': 0.17.0
|
||||
'@lexical/devtools-core': 0.17.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)
|
||||
'@lexical/dragon': 0.17.0
|
||||
'@lexical/hashtag': 0.17.0
|
||||
'@lexical/history': 0.17.0
|
||||
'@lexical/link': 0.17.0
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/mark': 0.17.0
|
||||
'@lexical/markdown': 0.17.0
|
||||
'@lexical/overflow': 0.17.0
|
||||
'@lexical/plain-text': 0.17.0
|
||||
'@lexical/rich-text': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/table': 0.17.0
|
||||
'@lexical/text': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
'@lexical/yjs': 0.17.0(yjs@13.6.18)
|
||||
lexical: 0.17.0
|
||||
'@lexical/clipboard': 0.18.0
|
||||
'@lexical/code': 0.18.0
|
||||
'@lexical/devtools-core': 0.18.0(react-dom@19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918))(react@19.0.0-rc-5dcb0097-20240918)
|
||||
'@lexical/dragon': 0.18.0
|
||||
'@lexical/hashtag': 0.18.0
|
||||
'@lexical/history': 0.18.0
|
||||
'@lexical/link': 0.18.0
|
||||
'@lexical/list': 0.18.0
|
||||
'@lexical/mark': 0.18.0
|
||||
'@lexical/markdown': 0.18.0
|
||||
'@lexical/overflow': 0.18.0
|
||||
'@lexical/plain-text': 0.18.0
|
||||
'@lexical/rich-text': 0.18.0
|
||||
'@lexical/selection': 0.18.0
|
||||
'@lexical/table': 0.18.0
|
||||
'@lexical/text': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
'@lexical/yjs': 0.18.0(yjs@13.6.18)
|
||||
lexical: 0.18.0
|
||||
react: 19.0.0-rc-5dcb0097-20240918
|
||||
react-dom: 19.0.0-rc-5dcb0097-20240918(react@19.0.0-rc-5dcb0097-20240918)
|
||||
react-error-boundary: 3.1.4(react@19.0.0-rc-5dcb0097-20240918)
|
||||
transitivePeerDependencies:
|
||||
- yjs
|
||||
|
||||
'@lexical/rich-text@0.17.0':
|
||||
'@lexical/rich-text@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/clipboard': 0.18.0
|
||||
'@lexical/selection': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/selection@0.17.0':
|
||||
'@lexical/selection@0.18.0':
|
||||
dependencies:
|
||||
lexical: 0.17.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/table@0.17.0':
|
||||
'@lexical/table@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/clipboard': 0.18.0
|
||||
'@lexical/utils': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/text@0.17.0':
|
||||
'@lexical/text@0.18.0':
|
||||
dependencies:
|
||||
lexical: 0.17.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/utils@0.17.0':
|
||||
'@lexical/utils@0.18.0':
|
||||
dependencies:
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/table': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/list': 0.18.0
|
||||
'@lexical/selection': 0.18.0
|
||||
'@lexical/table': 0.18.0
|
||||
lexical: 0.18.0
|
||||
|
||||
'@lexical/yjs@0.17.0(yjs@13.6.18)':
|
||||
'@lexical/yjs@0.18.0(yjs@13.6.18)':
|
||||
dependencies:
|
||||
'@lexical/offset': 0.17.0
|
||||
lexical: 0.17.0
|
||||
'@lexical/offset': 0.18.0
|
||||
'@lexical/selection': 0.18.0
|
||||
lexical: 0.18.0
|
||||
yjs: 13.6.18
|
||||
|
||||
'@libsql/client@0.6.2(bufferutil@4.0.8)(utf-8-validate@6.0.4)':
|
||||
@@ -16409,7 +16411,7 @@ snapshots:
|
||||
prelude-ls: 1.2.1
|
||||
type-check: 0.4.0
|
||||
|
||||
lexical@0.17.0: {}
|
||||
lexical@0.18.0: {}
|
||||
|
||||
lib0@0.2.97:
|
||||
dependencies:
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"@payloadcms/plugin-form-builder": "beta",
|
||||
"@payloadcms/plugin-nested-docs": "beta",
|
||||
"@payloadcms/plugin-redirects": "beta",
|
||||
"@payloadcms/plugin-search": "beta",
|
||||
"@payloadcms/plugin-seo": "beta",
|
||||
"@payloadcms/richtext-lexical": "beta",
|
||||
"@payloadcms/ui": "beta",
|
||||
@@ -38,7 +39,7 @@
|
||||
"geist": "^1.3.0",
|
||||
"graphql": "^16.8.2",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"lexical": "0.17.0",
|
||||
"lexical": "0.18.0",
|
||||
"lucide-react": "^0.378.0",
|
||||
"next": "15.0.0-canary.160",
|
||||
"payload": "beta",
|
||||
|
||||
10116
templates/website/pnpm-lock.yaml
generated
Normal file
10116
templates/website/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,8 @@ import React from 'react'
|
||||
import type { Header as HeaderType } from '@/payload-types'
|
||||
|
||||
import { CMSLink } from '@/components/Link'
|
||||
import Link from 'next/link'
|
||||
import { SearchIcon } from 'lucide-react'
|
||||
|
||||
export const HeaderNav: React.FC<{ header: HeaderType }> = ({ header }) => {
|
||||
const navItems = header?.navItems || []
|
||||
@@ -14,6 +16,10 @@ export const HeaderNav: React.FC<{ header: HeaderType }> = ({ header }) => {
|
||||
{navItems.map(({ link }, i) => {
|
||||
return <CMSLink key={i} {...link} appearance="link" />
|
||||
})}
|
||||
<Link href="/search">
|
||||
<span className="sr-only">Search</span>
|
||||
<SearchIcon className="w-5" />
|
||||
</Link>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export default async function Page({ params: { slug = 'home' } }) {
|
||||
})
|
||||
|
||||
// Remove this code once your website is seeded
|
||||
if (!page) {
|
||||
if (!page && slug === 'home') {
|
||||
page = homeStatic
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { draftMode } from 'next/headers'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { getPayloadHMR } from '@payloadcms/next/utilities'
|
||||
import configPromise from '@payload-config'
|
||||
import { CollectionSlug } from 'payload'
|
||||
|
||||
const payloadToken = 'payload-token'
|
||||
|
||||
@@ -19,29 +20,67 @@ export async function GET(
|
||||
const token = req.cookies.get(payloadToken)?.value
|
||||
const { searchParams } = new URL(req.url)
|
||||
const path = searchParams.get('path')
|
||||
const collection = searchParams.get('collection') as CollectionSlug
|
||||
const slug = searchParams.get('slug')
|
||||
|
||||
if (!path) {
|
||||
return new Response('No path provided', { status: 404 })
|
||||
}
|
||||
const previewSecret = searchParams.get('previewSecret')
|
||||
|
||||
if (!token) {
|
||||
new Response('You are not allowed to preview this page', { status: 403 })
|
||||
}
|
||||
|
||||
let user
|
||||
|
||||
try {
|
||||
user = jwt.verify(token, payload.secret)
|
||||
} catch (error) {
|
||||
payload.logger.error('Error verifying token for live preview:', error)
|
||||
}
|
||||
|
||||
// You can add additional checks here to see if the user is allowed to preview this page
|
||||
if (!user) {
|
||||
draftMode().disable()
|
||||
if (previewSecret) {
|
||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||
}
|
||||
} else {
|
||||
if (!path) {
|
||||
return new Response('No path provided', { status: 404 })
|
||||
}
|
||||
|
||||
draftMode().enable()
|
||||
redirect(path)
|
||||
if (!collection) {
|
||||
return new Response('No path provided', { status: 404 })
|
||||
}
|
||||
|
||||
if (!slug) {
|
||||
return new Response('No path provided', { status: 404 })
|
||||
}
|
||||
|
||||
if (!token) {
|
||||
new Response('You are not allowed to preview this page', { status: 403 })
|
||||
}
|
||||
|
||||
if (!path.startsWith('/')) {
|
||||
new Response('This endpoint can only be used for internal previews', { status: 500 })
|
||||
}
|
||||
|
||||
let user
|
||||
|
||||
try {
|
||||
user = jwt.verify(token, payload.secret)
|
||||
} catch (error) {
|
||||
payload.logger.error('Error verifying token for live preview:', error)
|
||||
}
|
||||
|
||||
// You can add additional checks here to see if the user is allowed to preview this page
|
||||
if (!user) {
|
||||
draftMode().disable()
|
||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||
}
|
||||
|
||||
// Verify the given slug exists
|
||||
try {
|
||||
const docs = await payload.find({
|
||||
collection: collection,
|
||||
where: {
|
||||
slug: {
|
||||
equals: slug,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (!docs.docs.length) {
|
||||
return new Response('Document not found', { status: 404 })
|
||||
}
|
||||
} catch (error) {
|
||||
payload.logger.error('Error verifying token for live preview:', error)
|
||||
}
|
||||
|
||||
draftMode().enable()
|
||||
redirect(path)
|
||||
}
|
||||
}
|
||||
|
||||
66
templates/website/src/app/(frontend)/search/page.tsx
Normal file
66
templates/website/src/app/(frontend)/search/page.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import type { Metadata } from 'next/types'
|
||||
|
||||
import { CollectionArchive } from '@/components/CollectionArchive'
|
||||
import configPromise from '@payload-config'
|
||||
import { getPayloadHMR } from '@payloadcms/next/utilities'
|
||||
import React from 'react'
|
||||
import { Post } from '@/payload-types'
|
||||
import { Search } from '@/search/Component'
|
||||
|
||||
export default async function Page({ searchParams }: { searchParams: { q: string } }) {
|
||||
const query = searchParams.q
|
||||
const payload = await getPayloadHMR({ config: configPromise })
|
||||
|
||||
const posts = await payload.find({
|
||||
collection: 'search',
|
||||
depth: 1,
|
||||
limit: 12,
|
||||
...(query
|
||||
? {
|
||||
where: {
|
||||
or: [
|
||||
{
|
||||
title: {
|
||||
like: query,
|
||||
},
|
||||
},
|
||||
{
|
||||
'meta.description': {
|
||||
like: query,
|
||||
},
|
||||
},
|
||||
{
|
||||
'meta.title': {
|
||||
like: query,
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: {
|
||||
like: query,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="pt-24 pb-24">
|
||||
<div className="container mb-16">
|
||||
<div className="prose dark:prose-invert max-w-none">
|
||||
<h1 className="sr-only">Search</h1>
|
||||
<Search />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CollectionArchive posts={posts.docs as unknown as Post[]} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function generateMetadata(): Metadata {
|
||||
return {
|
||||
title: `Payload Website Template Search`,
|
||||
}
|
||||
}
|
||||
@@ -16,29 +16,30 @@ import { PreviewComponent as PreviewComponent_14 } from '@payloadcms/plugin-seo/
|
||||
import { SlugComponent as SlugComponent_15 } from '@/fields/slug/SlugComponent'
|
||||
import { HorizontalRuleFeatureClient as HorizontalRuleFeatureClient_16 } from '@payloadcms/richtext-lexical/client'
|
||||
import { BlocksFeatureClient as BlocksFeatureClient_17 } from '@payloadcms/richtext-lexical/client'
|
||||
import { default as default_18 } from '@/components/BeforeDashboard'
|
||||
import { default as default_19 } from '@/components/BeforeLogin'
|
||||
import { LinkToDoc as LinkToDoc_18 } from '@payloadcms/plugin-search/client'
|
||||
import { default as default_19 } from '@/components/BeforeDashboard'
|
||||
import { default as default_20 } from '@/components/BeforeLogin'
|
||||
|
||||
export const importMap = {
|
||||
'@payloadcms/richtext-lexical/client#RichTextCell': RichTextCell_0,
|
||||
'@payloadcms/richtext-lexical/client#RichTextField': RichTextField_1,
|
||||
'@payloadcms/richtext-lexical/generateComponentMap#getGenerateComponentMap':
|
||||
getGenerateComponentMap_2,
|
||||
'@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient': InlineToolbarFeatureClient_3,
|
||||
'@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient': FixedToolbarFeatureClient_4,
|
||||
'@payloadcms/richtext-lexical/client#HeadingFeatureClient': HeadingFeatureClient_5,
|
||||
'@payloadcms/richtext-lexical/client#UnderlineFeatureClient': UnderlineFeatureClient_6,
|
||||
'@payloadcms/richtext-lexical/client#BoldFeatureClient': BoldFeatureClient_7,
|
||||
'@payloadcms/richtext-lexical/client#ItalicFeatureClient': ItalicFeatureClient_8,
|
||||
'@payloadcms/richtext-lexical/client#LinkFeatureClient': LinkFeatureClient_9,
|
||||
'@payloadcms/plugin-seo/client#OverviewComponent': OverviewComponent_10,
|
||||
'@payloadcms/plugin-seo/client#MetaTitleComponent': MetaTitleComponent_11,
|
||||
'@payloadcms/plugin-seo/client#MetaImageComponent': MetaImageComponent_12,
|
||||
'@payloadcms/plugin-seo/client#MetaDescriptionComponent': MetaDescriptionComponent_13,
|
||||
'@payloadcms/plugin-seo/client#PreviewComponent': PreviewComponent_14,
|
||||
'@/fields/slug/SlugComponent#SlugComponent': SlugComponent_15,
|
||||
'@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient': HorizontalRuleFeatureClient_16,
|
||||
'@payloadcms/richtext-lexical/client#BlocksFeatureClient': BlocksFeatureClient_17,
|
||||
'@/components/BeforeDashboard#default': default_18,
|
||||
'@/components/BeforeLogin#default': default_19,
|
||||
"@payloadcms/richtext-lexical/client#RichTextCell": RichTextCell_0,
|
||||
"@payloadcms/richtext-lexical/client#RichTextField": RichTextField_1,
|
||||
"@payloadcms/richtext-lexical/generateComponentMap#getGenerateComponentMap": getGenerateComponentMap_2,
|
||||
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_3,
|
||||
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_4,
|
||||
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_5,
|
||||
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_6,
|
||||
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_7,
|
||||
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_8,
|
||||
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_9,
|
||||
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_10,
|
||||
"@payloadcms/plugin-seo/client#MetaTitleComponent": MetaTitleComponent_11,
|
||||
"@payloadcms/plugin-seo/client#MetaImageComponent": MetaImageComponent_12,
|
||||
"@payloadcms/plugin-seo/client#MetaDescriptionComponent": MetaDescriptionComponent_13,
|
||||
"@payloadcms/plugin-seo/client#PreviewComponent": PreviewComponent_14,
|
||||
"@/fields/slug/SlugComponent#SlugComponent": SlugComponent_15,
|
||||
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_16,
|
||||
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_17,
|
||||
"@payloadcms/plugin-search/client#LinkToDoc": LinkToDoc_18,
|
||||
"@/components/BeforeDashboard#default": default_19,
|
||||
"@/components/BeforeLogin#default": default_20
|
||||
}
|
||||
|
||||
@@ -33,13 +33,21 @@ export const Pages: CollectionConfig = {
|
||||
livePreview: {
|
||||
url: ({ data }) => {
|
||||
const path = generatePreviewPath({
|
||||
path: `/${typeof data?.slug === 'string' ? data.slug : ''}`,
|
||||
slug: typeof data?.slug === 'string' ? data.slug : '',
|
||||
collection: 'pages',
|
||||
})
|
||||
|
||||
return `${process.env.NEXT_PUBLIC_SERVER_URL}${path}`
|
||||
},
|
||||
},
|
||||
preview: (doc) =>
|
||||
generatePreviewPath({ path: `/${typeof doc?.slug === 'string' ? doc.slug : ''}` }),
|
||||
preview: (data) => {
|
||||
const path = generatePreviewPath({
|
||||
slug: typeof data?.slug === 'string' ? data.slug : '',
|
||||
collection: 'pages',
|
||||
})
|
||||
|
||||
return `${process.env.NEXT_PUBLIC_SERVER_URL}${path}`
|
||||
},
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
|
||||
@@ -40,13 +40,21 @@ export const Posts: CollectionConfig = {
|
||||
livePreview: {
|
||||
url: ({ data }) => {
|
||||
const path = generatePreviewPath({
|
||||
path: `/posts/${typeof data?.slug === 'string' ? data.slug : ''}`,
|
||||
slug: typeof data?.slug === 'string' ? data.slug : '',
|
||||
collection: 'posts',
|
||||
})
|
||||
|
||||
return `${process.env.NEXT_PUBLIC_SERVER_URL}${path}`
|
||||
},
|
||||
},
|
||||
preview: (doc) =>
|
||||
generatePreviewPath({ path: `/posts/${typeof doc?.slug === 'string' ? doc.slug : ''}` }),
|
||||
preview: (data) => {
|
||||
const path = generatePreviewPath({
|
||||
slug: typeof data?.slug === 'string' ? data.slug : '',
|
||||
collection: 'posts',
|
||||
})
|
||||
|
||||
return `${process.env.NEXT_PUBLIC_SERVER_URL}${path}`
|
||||
},
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
|
||||
@@ -45,5 +45,6 @@ export const PayloadRedirects: React.FC<Props> = async ({ disableNotFound, url }
|
||||
}
|
||||
|
||||
if (disableNotFound) return null
|
||||
return notFound()
|
||||
|
||||
notFound()
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ const collections: CollectionSlug[] = [
|
||||
'posts',
|
||||
'forms',
|
||||
'form-submissions',
|
||||
'search',
|
||||
]
|
||||
const globals: GlobalSlug[] = ['header', 'footer']
|
||||
|
||||
@@ -65,7 +66,6 @@ export const seed = async ({
|
||||
}
|
||||
|
||||
for (const collection of collections) {
|
||||
console.log('delete', collection)
|
||||
await payload.delete({
|
||||
collection: collection,
|
||||
where: {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
TextInput,
|
||||
FieldLabel,
|
||||
useFormFields,
|
||||
useForm,
|
||||
} from '@payloadcms/ui'
|
||||
|
||||
import { formatSlug } from './formatSlug'
|
||||
@@ -33,33 +34,42 @@ export const SlugComponent: React.FC<SlugComponentProps> = ({
|
||||
|
||||
const { value, setValue } = useField<string>({ path })
|
||||
|
||||
const { value: checkboxValue, setValue: setCheckboxValue } = useField<boolean>({
|
||||
path: checkboxFieldPath,
|
||||
const { dispatchFields } = useForm()
|
||||
|
||||
// The value of the checkbox
|
||||
// We're using separate useFormFields to minimise re-renders
|
||||
const checkboxValue = useFormFields(([fields]) => {
|
||||
return fields[checkboxFieldPath]?.value as string
|
||||
})
|
||||
|
||||
const fieldToUseValue = useFormFields(([fields, dispatch]) => {
|
||||
// The value of the field we're listening to for the slug
|
||||
const targetFieldValue = useFormFields(([fields]) => {
|
||||
return fields[fieldToUse]?.value as string
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (checkboxValue) {
|
||||
if (fieldToUseValue) {
|
||||
const formattedSlug = formatSlug(fieldToUseValue)
|
||||
if (targetFieldValue) {
|
||||
const formattedSlug = formatSlug(targetFieldValue)
|
||||
|
||||
if (value !== formattedSlug) setValue(formattedSlug)
|
||||
} else {
|
||||
if (value !== '') setValue('')
|
||||
}
|
||||
}
|
||||
}, [fieldToUseValue, checkboxValue, setValue, value])
|
||||
}, [targetFieldValue, checkboxValue, setValue, value])
|
||||
|
||||
const handleLock = useCallback(
|
||||
(e) => {
|
||||
e.preventDefault()
|
||||
|
||||
setCheckboxValue(!checkboxValue)
|
||||
dispatchFields({
|
||||
type: 'UPDATE',
|
||||
path: checkboxFieldPath,
|
||||
value: !checkboxValue,
|
||||
})
|
||||
},
|
||||
[checkboxValue, setCheckboxValue],
|
||||
[checkboxValue, targetFieldValue],
|
||||
)
|
||||
|
||||
const readOnly = readOnlyFromProps || checkboxValue
|
||||
@@ -74,7 +84,7 @@ export const SlugComponent: React.FC<SlugComponentProps> = ({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<TextInput label={''} value={value} onChange={setValue} path={path} readOnly={readOnly} />
|
||||
<TextInput value={value} onChange={setValue} path={path} readOnly={Boolean(readOnly)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ export interface Config {
|
||||
redirects: Redirect;
|
||||
forms: Form;
|
||||
'form-submissions': FormSubmission;
|
||||
search: Search;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
@@ -578,6 +580,85 @@ export interface FormSubmission {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "search".
|
||||
*/
|
||||
export interface Search {
|
||||
id: string;
|
||||
title?: string | null;
|
||||
priority?: number | null;
|
||||
doc: {
|
||||
relationTo: 'posts';
|
||||
value: string | Post;
|
||||
};
|
||||
slug?: string | null;
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
image?: (string | null) | Media;
|
||||
};
|
||||
categories?:
|
||||
| {
|
||||
relationTo?: string | null;
|
||||
id?: string | null;
|
||||
title?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
*/
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?:
|
||||
| ({
|
||||
relationTo: 'pages';
|
||||
value: string | Page;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'posts';
|
||||
value: string | Post;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'media';
|
||||
value: string | Media;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'categories';
|
||||
value: string | Category;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'redirects';
|
||||
value: string | Redirect;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'forms';
|
||||
value: string | Form;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'form-submissions';
|
||||
value: string | FormSubmission;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'search';
|
||||
value: string | Search;
|
||||
} | null);
|
||||
globalSlug?: string | null;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
|
||||
@@ -6,6 +6,7 @@ import { formBuilderPlugin } from '@payloadcms/plugin-form-builder'
|
||||
import { nestedDocsPlugin } from '@payloadcms/plugin-nested-docs'
|
||||
import { redirectsPlugin } from '@payloadcms/plugin-redirects'
|
||||
import { seoPlugin } from '@payloadcms/plugin-seo'
|
||||
import { searchPlugin } from '@payloadcms/plugin-search'
|
||||
import {
|
||||
BoldFeature,
|
||||
FixedToolbarFeature,
|
||||
@@ -32,6 +33,9 @@ import { revalidateRedirects } from './hooks/revalidateRedirects'
|
||||
import { GenerateTitle, GenerateURL } from '@payloadcms/plugin-seo/types'
|
||||
import { Page, Post } from 'src/payload-types'
|
||||
|
||||
import { searchFields } from '@/search/fieldOverrides'
|
||||
import { beforeSyncWithSearch } from '@/search/beforeSync'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
@@ -188,6 +192,15 @@ export default buildConfig({
|
||||
},
|
||||
},
|
||||
}),
|
||||
searchPlugin({
|
||||
collections: ['posts'],
|
||||
beforeSync: beforeSyncWithSearch,
|
||||
searchOverrides: {
|
||||
fields: ({ defaultFields }) => {
|
||||
return [...defaultFields, ...searchFields]
|
||||
},
|
||||
},
|
||||
}),
|
||||
payloadCloudPlugin(), // storage-adapter-placeholder
|
||||
],
|
||||
secret: process.env.PAYLOAD_SECRET!,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user