Compare commits
13 Commits
feat/pushj
...
ui-strictN
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d45f203f16 | ||
|
|
967f8effd7 | ||
|
|
cac371bff9 | ||
|
|
2368f18b09 | ||
|
|
28334b7b76 | ||
|
|
7e7dd93554 | ||
|
|
71d969314c | ||
|
|
4781ee0afe | ||
|
|
04b1b27e55 | ||
|
|
4c8baf353f | ||
|
|
83d010db1d | ||
|
|
6870bff55b | ||
|
|
78811d31ff |
@@ -739,7 +739,7 @@ The `useDocumentInfo` hook provides information about the current document being
|
||||
| **`lastUpdateTime`** | Timestamp of the last update to the document. |
|
||||
| **`mostRecentVersionIsAutosaved`** | Whether the most recent version is an autosaved version. |
|
||||
| **`preferencesKey`** | The `preferences` key to use when interacting with document-level user preferences. [More details](./preferences). |
|
||||
| **`data`** | The saved data of the document. |
|
||||
| **`savedDocumentData`** | The saved data of the document. |
|
||||
| **`setDocFieldPreferences`** | Method to set preferences for a specific field. [More details](./preferences). |
|
||||
| **`setDocumentTitle`** | Method to set the document title. |
|
||||
| **`setHasPublishedDoc`** | Method to update whether the document has been published. |
|
||||
|
||||
@@ -142,7 +142,7 @@ The following options are available:
|
||||
| `components` | Swap in your own React components to be used within this Collection. [More details](#custom-components). |
|
||||
| `listSearchableFields` | Specify which fields should be searched in the List search view. [More details](#list-searchable-fields). |
|
||||
| `pagination` | Set pagination-specific options for this Collection. [More details](#pagination). |
|
||||
| `baseFilter` | Defines a default base filter which will be applied to the List View (along with any other filters applied by the user) and internal links in Lexical Editor, |
|
||||
| `baseListFilter` | You can define a default base filter for this collection's List view, which will be merged into any filters that the user performs. |
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:** If you set `useAsTitle` to a relationship or join field, it will use
|
||||
|
||||
@@ -54,15 +54,8 @@ The plugin accepts an object with the following properties:
|
||||
```ts
|
||||
type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
/**
|
||||
* Base path for your application
|
||||
*
|
||||
* https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath
|
||||
*
|
||||
* @default undefined
|
||||
*/
|
||||
basePath?: string
|
||||
/**
|
||||
* After a tenant is deleted, the plugin will attempt to clean up related documents
|
||||
* After a tenant is deleted, the plugin will attempt
|
||||
* to clean up related documents
|
||||
* - removing documents with the tenant ID
|
||||
* - removing the tenant from users
|
||||
*
|
||||
@@ -75,36 +68,22 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
collections: {
|
||||
[key in CollectionSlug]?: {
|
||||
/**
|
||||
* Set to `true` if you want the collection to behave as a global
|
||||
* Set to `true` if you want the collection to
|
||||
* behave as a global
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
isGlobal?: boolean
|
||||
/**
|
||||
* Overrides for the tenant field, will override the entire tenantField configuration
|
||||
*/
|
||||
tenantFieldOverrides?: CollectionTenantFieldConfigOverrides
|
||||
/**
|
||||
* Set to `false` if you want to manually apply the baseListFilter
|
||||
* Set to `false` if you want to manually apply the baseFilter
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
useBaseFilter?: boolean
|
||||
/**
|
||||
* @deprecated Use `useBaseFilter` instead. If both are defined,
|
||||
* `useBaseFilter` will take precedence. This property remains only
|
||||
* for backward compatibility and may be removed in a future version.
|
||||
*
|
||||
* Originally, `baseListFilter` was intended to filter only the List View
|
||||
* in the admin panel. However, base filtering is often required in other areas
|
||||
* such as internal link relationships in the Lexical editor.
|
||||
* Set to `false` if you want to manually apply
|
||||
* the baseListFilter
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
useBaseListFilter?: boolean
|
||||
/**
|
||||
* Set to `false` if you want to handle collection access manually without the multi-tenant constraints applied
|
||||
* Set to `false` if you want to handle collection access
|
||||
* manually without the multi-tenant constraints applied
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
@@ -113,7 +92,8 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
}
|
||||
/**
|
||||
* Enables debug mode
|
||||
* - Makes the tenant field visible in the admin UI within applicable collections
|
||||
* - Makes the tenant field visible in the
|
||||
* admin UI within applicable collections
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
@@ -125,41 +105,27 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
*/
|
||||
enabled?: boolean
|
||||
/**
|
||||
* Localization for the plugin
|
||||
* Field configuration for the field added
|
||||
* to all tenant enabled collections
|
||||
*/
|
||||
i18n?: {
|
||||
translations: {
|
||||
[key in AcceptedLanguages]?: {
|
||||
/**
|
||||
* @default 'You are about to change ownership from <0>{{fromTenant}}</0> to <0>{{toTenant}}</0>'
|
||||
*/
|
||||
'confirm-modal-tenant-switch--body'?: string
|
||||
/**
|
||||
* `tenantLabel` defaults to the value of the `nav-tenantSelector-label` translation
|
||||
*
|
||||
* @default 'Confirm {{tenantLabel}} change'
|
||||
*/
|
||||
'confirm-modal-tenant-switch--heading'?: string
|
||||
/**
|
||||
* @default 'Assigned Tenant'
|
||||
*/
|
||||
'field-assignedTenant-label'?: string
|
||||
/**
|
||||
* @default 'Tenant'
|
||||
*/
|
||||
'nav-tenantSelector-label'?: string
|
||||
}
|
||||
}
|
||||
tenantField?: {
|
||||
access?: RelationshipField['access']
|
||||
/**
|
||||
* The name of the field added to all tenant
|
||||
* enabled collections
|
||||
*
|
||||
* @default 'tenant'
|
||||
*/
|
||||
name?: string
|
||||
}
|
||||
/**
|
||||
* Field configuration for the field added to all tenant enabled collections
|
||||
*/
|
||||
tenantField?: RootTenantFieldConfigOverrides
|
||||
/**
|
||||
* Field configuration for the field added to the users collection
|
||||
* Field configuration for the field added
|
||||
* to the users collection
|
||||
*
|
||||
* If `includeDefaultField` is `false`, you must include the field on your users collection manually
|
||||
* This is useful if you want to customize the field or place the field in a specific location
|
||||
* If `includeDefaultField` is `false`, you must
|
||||
* include the field on your users collection manually
|
||||
* This is useful if you want to customize the field
|
||||
* or place the field in a specific location
|
||||
*/
|
||||
tenantsArrayField?:
|
||||
| {
|
||||
@@ -180,7 +146,8 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
*/
|
||||
arrayTenantFieldName?: string
|
||||
/**
|
||||
* When `includeDefaultField` is `true`, the field will be added to the users collection automatically
|
||||
* When `includeDefaultField` is `true`, the field will
|
||||
* be added to the users collection automatically
|
||||
*/
|
||||
includeDefaultField?: true
|
||||
/**
|
||||
@@ -197,7 +164,8 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
arrayFieldName?: string
|
||||
arrayTenantFieldName?: string
|
||||
/**
|
||||
* When `includeDefaultField` is `false`, you must include the field on your users collection manually
|
||||
* When `includeDefaultField` is `false`, you must
|
||||
* include the field on your users collection manually
|
||||
*/
|
||||
includeDefaultField?: false
|
||||
rowFields?: never
|
||||
@@ -206,9 +174,8 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
/**
|
||||
* Customize tenant selector label
|
||||
*
|
||||
* Either a string or an object where the keys are i18n codes and the values are the string labels
|
||||
*
|
||||
* @deprecated Use `i18n.translations` instead.
|
||||
* Either a string or an object where the keys are i18n
|
||||
* codes and the values are the string labels
|
||||
*/
|
||||
tenantSelectorLabel?:
|
||||
| Partial<{
|
||||
@@ -222,25 +189,27 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
*/
|
||||
tenantsSlug?: string
|
||||
/**
|
||||
* Function that determines if a user has access to _all_ tenants
|
||||
* Function that determines if a user has access
|
||||
* to _all_ tenants
|
||||
*
|
||||
* Useful for super-admin type users
|
||||
*/
|
||||
userHasAccessToAllTenants?: (
|
||||
user: ConfigTypes extends { user: unknown }
|
||||
? ConfigTypes['user']
|
||||
: TypedUser,
|
||||
user: ConfigTypes extends { user: unknown } ? ConfigTypes['user'] : User,
|
||||
) => boolean
|
||||
/**
|
||||
* Opt out of adding access constraints to the tenants collection
|
||||
* Opt out of adding access constraints to
|
||||
* the tenants collection
|
||||
*/
|
||||
useTenantsCollectionAccess?: boolean
|
||||
/**
|
||||
* Opt out including the baseListFilter to filter tenants by selected tenant
|
||||
* Opt out including the baseListFilter to filter
|
||||
* tenants by selected tenant
|
||||
*/
|
||||
useTenantsListFilter?: boolean
|
||||
/**
|
||||
* Opt out including the baseListFilter to filter users by selected tenant
|
||||
* Opt out including the baseListFilter to filter
|
||||
* users by selected tenant
|
||||
*/
|
||||
useUsersTenantFilter?: boolean
|
||||
}
|
||||
|
||||
@@ -6,112 +6,9 @@ desc: Troubleshooting Common Issues in Payload
|
||||
keywords: admin, components, custom, customize, documentation, Content Management System, cms, headless, javascript, node, react, nextjs, troubleshooting
|
||||
---
|
||||
|
||||
## Dependency mismatches
|
||||
## Common Issues
|
||||
|
||||
All `payload` and `@payloadcms/*` packages must be on exactly the same version and installed only once.
|
||||
|
||||
When two copies—or two different versions—of any of these packages (or of `react` / `react-dom`) appear in your dependency graph, you can see puzzling runtime errors. The most frequent is a broken React context:
|
||||
|
||||
```bash
|
||||
TypeError: Cannot destructure property 'config' of...
|
||||
```
|
||||
|
||||
This happens because one package imports a hook (most commonly `useConfig`) from _version A_ while the context provider comes from _version B_. The fix is always the same: make sure every Payload-related and React package resolves to the same module.
|
||||
|
||||
### Confirm whether duplicates exist
|
||||
|
||||
The first thing to do is to confirm whether duplicative dependencies do in fact exist.
|
||||
|
||||
There are two ways to do this:
|
||||
|
||||
1. Using pnpm's built-in inspection tool
|
||||
|
||||
```bash
|
||||
pnpm why @payloadcms/ui
|
||||
```
|
||||
|
||||
This prints the dependency tree and shows which versions are being installed. If you see more than one distinct version—or the same version listed under different paths—you have duplication.
|
||||
|
||||
2. Manual check (works with any package manager)
|
||||
|
||||
```bash
|
||||
find node_modules -name package.json \
|
||||
-exec grep -H '"name": "@payloadcms/ui"' {} \;
|
||||
```
|
||||
|
||||
Most of these hits are likely symlinks created by pnpm. Edit the matching package.json files (temporarily add a comment or change a description) to confirm whether they point to the same physical folder or to multiple copies.
|
||||
|
||||
Perform the same two checks for react and react-dom; a second copy of React can cause identical symptoms.
|
||||
|
||||
#### If no duplicates are found
|
||||
|
||||
`@payloadcms/ui` intentionally contains two bundles of itself, so you may see dual paths even when everything is correct. Inside the Payload Admin UI you must import only:
|
||||
|
||||
- `@payloadcms/ui`
|
||||
- `@payloadcms/ui/rsc`
|
||||
- `@payloadcms/ui/shared`
|
||||
|
||||
Any other deep import such as `@payloadcms/ui/elements/Button` should **only** be used in your own frontend, outside of the Payload Admin Panel. Those deep entries are published un-bundled to help you tree-shake and ship a smaller client bundle if you only need a few components from `@payloadcms/ui`.
|
||||
|
||||
### Fixing depedendency issues
|
||||
|
||||
These steps assume `pnpm`, which the Payload team recommends and uses internally. The principles apply to other package managers like npm and yarn as well. Do note that yarn 1.x is not supported by Payload.
|
||||
|
||||
1. Pin every critical package to an exact version
|
||||
|
||||
In package.json remove `^` or `~` from all versions of:
|
||||
|
||||
- `payload`
|
||||
- `@payloadcms/*`
|
||||
- `react`
|
||||
- `react-dom`
|
||||
|
||||
Prefixes allow your package manager to float to a newer minor/patch release, causing mismatches.
|
||||
|
||||
2. Delete node_modules
|
||||
|
||||
Old packages often linger even after you change versions or removed them from your package.json. Deleting node_modules ensures a clean slate.
|
||||
|
||||
3. Re-install dependencies
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
#### If the error persists
|
||||
|
||||
1. Clean the global store (pnpm only)
|
||||
|
||||
```bash
|
||||
pnpm store prune
|
||||
```
|
||||
|
||||
2. Delete the lockfile
|
||||
|
||||
Depending on your package manager, this could be `pnpm-lock.yaml`, `package-lock.json`, or `yarn.lock`.
|
||||
|
||||
Make sure you delete the lockfile **and** the node_modules folder at the same time, then run `pnpm install`. This forces a fresh, consistent resolution for all packages. It will also update all packages with dynamic versions to the latest version.
|
||||
|
||||
While it's best practice to manage dependencies in such a way where the lockfile can easily be re-generated (often this is the easiest way to resolve dependency issues), this may break your project if you have not tested the latest versions of your dependencies.
|
||||
|
||||
If you are using a version control system, make sure to commit your lockfile after this step.
|
||||
|
||||
3. Deduplicate anything that slipped through
|
||||
|
||||
```bash
|
||||
pnpm dedupe
|
||||
```
|
||||
|
||||
**Still stuck?**
|
||||
|
||||
- Switch to `pnpm` if you are on npm. Its symlinked store helps reducing accidental duplication.
|
||||
- Inspect the lockfile directly for peer-dependency violations.
|
||||
- Check project-level .npmrc / .pnpmfile.cjs overrides.
|
||||
- Run [Syncpack](https://www.npmjs.com/package/syncpack) to enforce identical versions of every `@payloadcms/*`, `react`, and `react-dom` reference.
|
||||
|
||||
Absolute last resort: add Webpack aliases so that all imports of a given package resolve to the same path (e.g. `resolve.alias['react'] = path.resolve('./node_modules/react')`). Keep this only until you can fix the underlying version skew.
|
||||
|
||||
## "Unauthorized, you must be logged in to make this request" when attempting to log in
|
||||
### "Unauthorized, you must be logged in to make this request" when attempting to log in
|
||||
|
||||
This means that your auth cookie is not being set or accepted correctly upon logging in. To resolve check the following settings in your Payload Config:
|
||||
|
||||
|
||||
@@ -50,18 +50,12 @@ export const updateOne: UpdateOne = async function updateOne(
|
||||
|
||||
let result
|
||||
|
||||
let updateData: UpdateQuery<any> = data
|
||||
|
||||
const $inc: Record<string, number> = {}
|
||||
const $push: Record<string, { $each: any[] } | any> = {}
|
||||
|
||||
transform({ $inc, $push, adapter: this, data, fields, operation: 'write' })
|
||||
let updateData: UpdateQuery<any> = data
|
||||
transform({ $inc, adapter: this, data, fields, operation: 'write' })
|
||||
if (Object.keys($inc).length) {
|
||||
updateData = { $inc, $set: updateData }
|
||||
}
|
||||
if (Object.keys($push).length) {
|
||||
updateData = { $push, $set: updateData }
|
||||
}
|
||||
|
||||
try {
|
||||
if (returning === false) {
|
||||
|
||||
@@ -209,7 +209,6 @@ const sanitizeDate = ({
|
||||
|
||||
type Args = {
|
||||
$inc?: Record<string, number>
|
||||
$push?: Record<string, { $each: any[] } | any>
|
||||
/** instance of the adapter */
|
||||
adapter: MongooseAdapter
|
||||
/** data to transform, can be an array of documents or a single document */
|
||||
@@ -399,7 +398,6 @@ const stripFields = ({
|
||||
|
||||
export const transform = ({
|
||||
$inc,
|
||||
$push,
|
||||
adapter,
|
||||
data,
|
||||
fields,
|
||||
@@ -414,16 +412,7 @@ export const transform = ({
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
for (const item of data) {
|
||||
transform({
|
||||
$inc,
|
||||
$push,
|
||||
adapter,
|
||||
data: item,
|
||||
fields,
|
||||
globalSlug,
|
||||
operation,
|
||||
validateRelationships,
|
||||
})
|
||||
transform({ $inc, adapter, data: item, fields, globalSlug, operation, validateRelationships })
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -481,26 +470,6 @@ export const transform = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
$push &&
|
||||
field.type === 'array' &&
|
||||
operation === 'write' &&
|
||||
field.name in ref &&
|
||||
ref[field.name]
|
||||
) {
|
||||
const value = ref[field.name]
|
||||
if (value && typeof value === 'object' && '$push' in value) {
|
||||
const push = value.$push
|
||||
|
||||
if (Array.isArray(push)) {
|
||||
$push[`${parentPath}${field.name}`] = { $each: push }
|
||||
} else if (typeof push === 'object') {
|
||||
$push[`${parentPath}${field.name}`] = push
|
||||
}
|
||||
delete ref[field.name]
|
||||
}
|
||||
}
|
||||
|
||||
if (field.type === 'date' && operation === 'read' && field.name in ref && ref[field.name]) {
|
||||
if (config.localization && fieldShouldBeLocalized({ field, parentIsLocalized })) {
|
||||
const fieldRef = ref[field.name] as Record<string, unknown>
|
||||
|
||||
@@ -166,8 +166,10 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
|
||||
countVersions,
|
||||
create,
|
||||
createGlobal,
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
createGlobalVersion,
|
||||
createJSONQuery,
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
createVersion,
|
||||
defaultIDType: payloadIDType,
|
||||
deleteMany,
|
||||
@@ -206,9 +208,11 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
|
||||
resolveInitializing,
|
||||
rollbackTransaction,
|
||||
updateGlobal,
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
updateGlobalVersion,
|
||||
updateMany,
|
||||
updateOne,
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
updateVersion,
|
||||
upsert,
|
||||
})
|
||||
|
||||
@@ -71,7 +71,6 @@ export const transformArray = ({
|
||||
data.forEach((arrayRow, i) => {
|
||||
const newRow: ArrayRowToInsert = {
|
||||
arrays: {},
|
||||
arraysToPush: {},
|
||||
locales: {},
|
||||
row: {
|
||||
_order: i + 1,
|
||||
@@ -105,7 +104,6 @@ export const transformArray = ({
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: newRow.arrays,
|
||||
arraysToPush: newRow.arraysToPush,
|
||||
baseTableName,
|
||||
blocks,
|
||||
blocksToDelete,
|
||||
|
||||
@@ -78,7 +78,6 @@ export const transformBlocks = ({
|
||||
|
||||
const newRow: BlockRowToInsert = {
|
||||
arrays: {},
|
||||
arraysToPush: {},
|
||||
locales: {},
|
||||
row: {
|
||||
_order: i + 1,
|
||||
@@ -117,7 +116,6 @@ export const transformBlocks = ({
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: newRow.arrays,
|
||||
arraysToPush: newRow.arraysToPush,
|
||||
baseTableName,
|
||||
blocks,
|
||||
blocksToDelete,
|
||||
|
||||
@@ -27,7 +27,6 @@ export const transformForWrite = ({
|
||||
// Split out the incoming data into rows to insert / delete
|
||||
const rowToInsert: RowToInsert = {
|
||||
arrays: {},
|
||||
arraysToPush: {},
|
||||
blocks: {},
|
||||
blocksToDelete: new Set(),
|
||||
locales: {},
|
||||
@@ -46,7 +45,6 @@ export const transformForWrite = ({
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: rowToInsert.arrays,
|
||||
arraysToPush: rowToInsert.arraysToPush,
|
||||
baseTableName: tableName,
|
||||
blocks: rowToInsert.blocks,
|
||||
blocksToDelete: rowToInsert.blocksToDelete,
|
||||
|
||||
@@ -4,7 +4,13 @@ import { fieldIsVirtual, fieldShouldBeLocalized } from 'payload/shared'
|
||||
import toSnakeCase from 'to-snake-case'
|
||||
|
||||
import type { DrizzleAdapter } from '../../types.js'
|
||||
import type { NumberToDelete, RelationshipToDelete, RowToInsert, TextToDelete } from './types.js'
|
||||
import type {
|
||||
ArrayRowToInsert,
|
||||
BlockRowToInsert,
|
||||
NumberToDelete,
|
||||
RelationshipToDelete,
|
||||
TextToDelete,
|
||||
} from './types.js'
|
||||
|
||||
import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'
|
||||
import { resolveBlockTableName } from '../../utilities/validateExistingBlockIsIdentical.js'
|
||||
@@ -17,20 +23,16 @@ import { transformTexts } from './texts.js'
|
||||
|
||||
type Args = {
|
||||
adapter: DrizzleAdapter
|
||||
/**
|
||||
* This will delete the array table and then re-insert all the new array rows.
|
||||
*/
|
||||
arrays: RowToInsert['arrays']
|
||||
/**
|
||||
* Array rows to push to the existing array. This will simply create
|
||||
* a new row in the array table.
|
||||
*/
|
||||
arraysToPush: RowToInsert['arraysToPush']
|
||||
arrays: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
/**
|
||||
* This is the name of the base table
|
||||
*/
|
||||
baseTableName: string
|
||||
blocks: RowToInsert['blocks']
|
||||
blocks: {
|
||||
[blockType: string]: BlockRowToInsert[]
|
||||
}
|
||||
blocksToDelete: Set<string>
|
||||
/**
|
||||
* A snake-case field prefix, representing prior fields
|
||||
@@ -80,7 +82,6 @@ type Args = {
|
||||
export const traverseFields = ({
|
||||
adapter,
|
||||
arrays,
|
||||
arraysToPush,
|
||||
baseTableName,
|
||||
blocks,
|
||||
blocksToDelete,
|
||||
@@ -128,6 +129,10 @@ export const traverseFields = ({
|
||||
if (field.type === 'array') {
|
||||
const arrayTableName = adapter.tableNameMap.get(`${parentTableName}_${columnName}`)
|
||||
|
||||
if (!arrays[arrayTableName]) {
|
||||
arrays[arrayTableName] = []
|
||||
}
|
||||
|
||||
if (isLocalized) {
|
||||
if (typeof data[field.name] === 'object' && data[field.name] !== null) {
|
||||
Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {
|
||||
@@ -152,33 +157,19 @@ export const traverseFields = ({
|
||||
textsToDelete,
|
||||
withinArrayOrBlockLocale: localeKey,
|
||||
})
|
||||
if (!arrays[arrayTableName]) {
|
||||
arrays[arrayTableName] = []
|
||||
}
|
||||
|
||||
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
let value = data[field.name]
|
||||
let push = false
|
||||
if (
|
||||
// TODO do this for localized as well in DRY way
|
||||
|
||||
typeof value === 'object' &&
|
||||
'$push' in value
|
||||
) {
|
||||
value = Array.isArray(value.$push) ? value.$push : [value.$push]
|
||||
push = true
|
||||
}
|
||||
|
||||
const newRows = transformArray({
|
||||
adapter,
|
||||
arrayTableName,
|
||||
baseTableName,
|
||||
blocks,
|
||||
blocksToDelete,
|
||||
data: value,
|
||||
data: data[field.name],
|
||||
field,
|
||||
numbers,
|
||||
numbersToDelete,
|
||||
@@ -192,17 +183,7 @@ export const traverseFields = ({
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
|
||||
if (push) {
|
||||
if (!arraysToPush[arrayTableName]) {
|
||||
arraysToPush[arrayTableName] = []
|
||||
}
|
||||
arraysToPush[arrayTableName] = arraysToPush[arrayTableName].concat(newRows)
|
||||
} else {
|
||||
if (!arrays[arrayTableName]) {
|
||||
arrays[arrayTableName] = []
|
||||
}
|
||||
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
|
||||
}
|
||||
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
|
||||
}
|
||||
|
||||
return
|
||||
@@ -283,7 +264,6 @@ export const traverseFields = ({
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
arraysToPush,
|
||||
baseTableName,
|
||||
blocks,
|
||||
blocksToDelete,
|
||||
@@ -318,7 +298,6 @@ export const traverseFields = ({
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
arraysToPush,
|
||||
baseTableName,
|
||||
blocks,
|
||||
blocksToDelete,
|
||||
|
||||
@@ -2,9 +2,6 @@ export type ArrayRowToInsert = {
|
||||
arrays: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
arraysToPush: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
locales: {
|
||||
[locale: string]: Record<string, unknown>
|
||||
}
|
||||
@@ -15,9 +12,6 @@ export type BlockRowToInsert = {
|
||||
arrays: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
arraysToPush: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
locales: {
|
||||
[locale: string]: Record<string, unknown>
|
||||
}
|
||||
@@ -43,9 +37,6 @@ export type RowToInsert = {
|
||||
arrays: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
arraysToPush: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
blocks: {
|
||||
[tableName: string]: BlockRowToInsert[]
|
||||
}
|
||||
|
||||
@@ -13,13 +13,9 @@ export const updateJobs: UpdateJobs = async function updateMany(
|
||||
this: DrizzleAdapter,
|
||||
{ id, data, limit: limitArg, req, returning, sort: sortArg, where: whereArg },
|
||||
) {
|
||||
if (
|
||||
!(data?.log as object[])?.length &&
|
||||
!(data.log && typeof data.log === 'object' && '$push' in data.log)
|
||||
) {
|
||||
if (!(data?.log as object[])?.length) {
|
||||
delete data.log
|
||||
}
|
||||
|
||||
const whereToUse: Where = id ? { id: { equals: id } } : whereArg
|
||||
const limit = id ? 1 : limitArg
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
}: Args): Promise<T> => {
|
||||
let insertedRow: Record<string, unknown> = { id }
|
||||
if (id && shouldUseOptimizedUpsertRow({ data, fields })) {
|
||||
const { arraysToPush, row } = transformForWrite({
|
||||
const { row } = transformForWrite({
|
||||
adapter,
|
||||
data,
|
||||
enableAtomicWrites: true,
|
||||
@@ -54,27 +54,11 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
|
||||
const drizzle = db as LibSQLDatabase
|
||||
|
||||
// First, handle $push arrays
|
||||
|
||||
if (arraysToPush && Object.keys(arraysToPush)?.length) {
|
||||
await insertArrays({
|
||||
adapter,
|
||||
arrays: [arraysToPush],
|
||||
db,
|
||||
parentRows: [insertedRow],
|
||||
uuidMap: {},
|
||||
})
|
||||
}
|
||||
|
||||
// Then, handle regular row update
|
||||
|
||||
if (ignoreResult) {
|
||||
if (row && Object.keys(row).length) {
|
||||
await drizzle
|
||||
.update(adapter.tables[tableName])
|
||||
.set(row)
|
||||
.where(eq(adapter.tables[tableName].id, id))
|
||||
}
|
||||
await drizzle
|
||||
.update(adapter.tables[tableName])
|
||||
.set(row)
|
||||
.where(eq(adapter.tables[tableName].id, id))
|
||||
return ignoreResult === 'idOnly' ? ({ id } as T) : null
|
||||
}
|
||||
|
||||
@@ -90,22 +74,6 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
const findManyKeysLength = Object.keys(findManyArgs).length
|
||||
const hasOnlyColumns = Object.keys(findManyArgs.columns || {}).length > 0
|
||||
|
||||
if (!row || !Object.keys(row).length) {
|
||||
// Nothing to update => just fetch current row and return
|
||||
findManyArgs.where = eq(adapter.tables[tableName].id, insertedRow.id)
|
||||
|
||||
const doc = await db.query[tableName].findFirst(findManyArgs)
|
||||
|
||||
return transform<T>({
|
||||
adapter,
|
||||
config: adapter.payload.config,
|
||||
data: doc,
|
||||
fields,
|
||||
joinQuery: false,
|
||||
tableName,
|
||||
})
|
||||
}
|
||||
|
||||
if (findManyKeysLength === 0 || hasOnlyColumns) {
|
||||
// Optimization - No need for joins => can simply use returning(). This is optimal for very simple collections
|
||||
// without complex fields that live in separate tables like blocks, arrays, relationships, etc.
|
||||
@@ -461,9 +429,9 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
|
||||
await insertArrays({
|
||||
adapter,
|
||||
arrays: [rowToInsert.arrays, rowToInsert.arraysToPush],
|
||||
arrays: [rowToInsert.arrays],
|
||||
db,
|
||||
parentRows: [insertedRow, insertedRow],
|
||||
parentRows: [insertedRow],
|
||||
uuidMap: arraysBlocksUUIDMap,
|
||||
})
|
||||
|
||||
|
||||
@@ -32,9 +32,6 @@ export const insertArrays = async ({
|
||||
const rowsByTable: RowsByTable = {}
|
||||
|
||||
arrays.forEach((arraysByTable, parentRowIndex) => {
|
||||
if (!arraysByTable || Object.keys(arraysByTable).length === 0) {
|
||||
return
|
||||
}
|
||||
Object.entries(arraysByTable).forEach(([tableName, arrayRows]) => {
|
||||
// If the table doesn't exist in map, initialize it
|
||||
if (!rowsByTable[tableName]) {
|
||||
|
||||
@@ -20,6 +20,7 @@ export const shouldUseOptimizedUpsertRow = ({
|
||||
}
|
||||
|
||||
if (
|
||||
field.type === 'array' ||
|
||||
field.type === 'blocks' ||
|
||||
((field.type === 'text' ||
|
||||
field.type === 'relationship' ||
|
||||
@@ -34,17 +35,6 @@ export const shouldUseOptimizedUpsertRow = ({
|
||||
return false
|
||||
}
|
||||
|
||||
if (field.type === 'array') {
|
||||
if (typeof value === 'object' && '$push' in value && value.$push) {
|
||||
return shouldUseOptimizedUpsertRow({
|
||||
// Only check first row - this function cares about field definitions. Each array row will have the same field definitions.
|
||||
data: Array.isArray(value.$push) ? value.$push?.[0] : value.$push,
|
||||
fields: field.flattenedFields,
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if (
|
||||
(field.type === 'group' || field.type === 'tab') &&
|
||||
value &&
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
@import '~@payloadcms/ui/scss';
|
||||
|
||||
$tab-width: 24px;
|
||||
$tab-width: 16px;
|
||||
|
||||
@layer payload-default {
|
||||
.query-inspector {
|
||||
--tab-width: 24px;
|
||||
|
||||
&__json-children {
|
||||
position: relative;
|
||||
|
||||
&--nested {
|
||||
& li {
|
||||
padding-left: 8px;
|
||||
padding-left: $tab-width;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,14 +23,6 @@ $tab-width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&__row-line {
|
||||
&--nested {
|
||||
.query-inspector__json-children {
|
||||
padding-left: var(--tab-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__list-wrap {
|
||||
position: relative;
|
||||
}
|
||||
@@ -47,16 +37,10 @@ $tab-width: 24px;
|
||||
border-bottom-right-radius: 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
column-gap: 14px;
|
||||
row-gap: 10px;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
left: 0;
|
||||
left: -3px;
|
||||
width: calc(100% + 3px);
|
||||
background-color: var(--theme-elevation-50);
|
||||
|
||||
&:not(.query-inspector__list-toggle--empty) {
|
||||
margin-left: calc(var(--tab-width) * -1 - 10px);
|
||||
}
|
||||
|
||||
svg .stroke {
|
||||
stroke: var(--theme-elevation-400);
|
||||
@@ -98,31 +82,13 @@ $tab-width: 24px;
|
||||
&__bracket {
|
||||
position: relative;
|
||||
|
||||
&--position-end {
|
||||
left: 2px;
|
||||
width: calc(100% - 5px);
|
||||
&--nested {
|
||||
margin-left: $tab-width;
|
||||
}
|
||||
}
|
||||
|
||||
// Some specific rules targetting the very top of the nested JSON structure or very first items since they need slightly different styling
|
||||
&__results {
|
||||
& > .query-inspector__row-line--nested {
|
||||
& > .query-inspector__list-toggle {
|
||||
margin-left: 0;
|
||||
column-gap: 6px;
|
||||
|
||||
.query-inspector__toggle-row-icon {
|
||||
margin-left: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
& > .query-inspector__json-children {
|
||||
padding-left: calc(var(--base) * 1);
|
||||
}
|
||||
|
||||
& > .query-inspector__bracket--nested > .query-inspector__bracket--position-end {
|
||||
padding-left: 16px;
|
||||
}
|
||||
&--position-end {
|
||||
left: 1px;
|
||||
width: calc(100% - 5px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ export const handleGroupBy = async ({
|
||||
},
|
||||
})
|
||||
|
||||
let heading = valueOrRelationshipID
|
||||
let heading = valueOrRelationshipID || req.i18n.t('general:noValue')
|
||||
|
||||
if (
|
||||
groupByField?.type === 'relationship' &&
|
||||
@@ -155,24 +155,14 @@ export const handleGroupBy = async ({
|
||||
valueOrRelationshipID
|
||||
}
|
||||
|
||||
if (groupByField.type === 'date' && valueOrRelationshipID) {
|
||||
if (groupByField.type === 'date') {
|
||||
heading = formatDate({
|
||||
date: String(valueOrRelationshipID),
|
||||
date: String(heading),
|
||||
i18n: req.i18n,
|
||||
pattern: clientConfig.admin.dateFormat,
|
||||
})
|
||||
}
|
||||
|
||||
if (groupByField.type === 'checkbox') {
|
||||
if (valueOrRelationshipID === true) {
|
||||
heading = req.i18n.t('general:true')
|
||||
}
|
||||
|
||||
if (valueOrRelationshipID === false) {
|
||||
heading = req.i18n.t('general:false')
|
||||
}
|
||||
}
|
||||
|
||||
if (groupData.docs && groupData.docs.length > 0) {
|
||||
const { columnState: newColumnState, Table: NewTable } = renderTable({
|
||||
clientCollectionConfig,
|
||||
@@ -184,7 +174,7 @@ export const handleGroupBy = async ({
|
||||
enableRowSelections,
|
||||
groupByFieldPath,
|
||||
groupByValue: valueOrRelationshipID,
|
||||
heading: heading || req.i18n.t('general:noValue'),
|
||||
heading,
|
||||
i18n: req.i18n,
|
||||
key: `table-${valueOrRelationshipID}`,
|
||||
orderableFieldName: collectionConfig.orderable === true ? '_order' : undefined,
|
||||
|
||||
@@ -138,14 +138,16 @@ export const renderListView = async (
|
||||
throw new Error('not-found')
|
||||
}
|
||||
|
||||
const baseFilterConstraint = await (
|
||||
collectionConfig.admin?.baseFilter ?? collectionConfig.admin?.baseListFilter
|
||||
)?.({
|
||||
limit: query.limit,
|
||||
page: query.page,
|
||||
req,
|
||||
sort: query.sort,
|
||||
})
|
||||
let baseListFilter = undefined
|
||||
|
||||
if (typeof collectionConfig.admin?.baseListFilter === 'function') {
|
||||
baseListFilter = await collectionConfig.admin.baseListFilter({
|
||||
limit: query.limit,
|
||||
page: query.page,
|
||||
req,
|
||||
sort: query.sort,
|
||||
})
|
||||
}
|
||||
|
||||
let queryPreset: QueryPreset | undefined
|
||||
let queryPresetPermissions: SanitizedCollectionPermission | undefined
|
||||
@@ -153,7 +155,7 @@ export const renderListView = async (
|
||||
let whereWithMergedSearch = mergeListSearchAndWhere({
|
||||
collectionConfig,
|
||||
search: typeof query?.search === 'string' ? query.search : undefined,
|
||||
where: combineWhereConstraints([query?.where, baseFilterConstraint]),
|
||||
where: combineWhereConstraints([query?.where, baseListFilter]),
|
||||
})
|
||||
|
||||
if (trash === true) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export type ServerOnlyCollectionProperties = keyof Pick<
|
||||
|
||||
export type ServerOnlyCollectionAdminProperties = keyof Pick<
|
||||
SanitizedCollectionConfig['admin'],
|
||||
'baseFilter' | 'baseListFilter' | 'components' | 'hidden'
|
||||
'baseListFilter' | 'components' | 'hidden'
|
||||
>
|
||||
|
||||
export type ServerOnlyUploadProperties = keyof Pick<
|
||||
@@ -94,7 +94,6 @@ const serverOnlyUploadProperties: Partial<ServerOnlyUploadProperties>[] = [
|
||||
|
||||
const serverOnlyCollectionAdminProperties: Partial<ServerOnlyCollectionAdminProperties>[] = [
|
||||
'hidden',
|
||||
'baseFilter',
|
||||
'baseListFilter',
|
||||
'components',
|
||||
// 'preview' is handled separately
|
||||
|
||||
@@ -270,7 +270,7 @@ export type EnableFoldersOptions = {
|
||||
debug?: boolean
|
||||
}
|
||||
|
||||
export type BaseFilter = (args: {
|
||||
export type BaseListFilter = (args: {
|
||||
limit: number
|
||||
locale?: TypedLocale
|
||||
page: number
|
||||
@@ -278,31 +278,7 @@ export type BaseFilter = (args: {
|
||||
sort: string
|
||||
}) => null | Promise<null | Where> | Where
|
||||
|
||||
/**
|
||||
* @deprecated Use `BaseFilter` instead.
|
||||
*/
|
||||
export type BaseListFilter = BaseFilter
|
||||
|
||||
export type CollectionAdminOptions = {
|
||||
/**
|
||||
* Defines a default base filter which will be applied in the following parts of the admin panel:
|
||||
* - List View
|
||||
* - Relationship fields for internal links within the Lexical editor
|
||||
*
|
||||
* This is especially useful for plugins like multi-tenant. For example,
|
||||
* a user may have access to multiple tenants, but should only see content
|
||||
* related to the currently active or selected tenant in those places.
|
||||
*/
|
||||
baseFilter?: BaseFilter
|
||||
/**
|
||||
* @deprecated Use `baseFilter` instead. If both are defined,
|
||||
* `baseFilter` will take precedence. This property remains only
|
||||
* for backward compatibility and may be removed in a future version.
|
||||
*
|
||||
* Originally, `baseListFilter` was intended to filter only the List View
|
||||
* in the admin panel. However, base filtering is often required in other areas
|
||||
* such as internal link relationships in the Lexical editor.
|
||||
*/
|
||||
baseListFilter?: BaseListFilter
|
||||
/**
|
||||
* Custom admin components
|
||||
|
||||
@@ -14,7 +14,6 @@ export const baseIDField: TextField = {
|
||||
defaultValue: () => new ObjectId().toHexString(),
|
||||
hooks: {
|
||||
beforeChange: [({ value }) => value || new ObjectId().toHexString()],
|
||||
// ID field values for arrays and blocks need to be unique when duplicating, as on postgres they are stored on the same table as primary keys.
|
||||
beforeDuplicate: [() => new ObjectId().toHexString()],
|
||||
},
|
||||
label: 'ID',
|
||||
|
||||
@@ -63,8 +63,7 @@ export const promise = async <T>({
|
||||
let fieldData = siblingDoc?.[field.name!]
|
||||
const fieldIsLocalized = localization && fieldShouldBeLocalized({ field, parentIsLocalized })
|
||||
|
||||
// Run field beforeDuplicate hooks.
|
||||
// These hooks are responsible for resetting the `id` field values of array and block rows. See `baseIDField`.
|
||||
// Run field beforeDuplicate hooks
|
||||
if (Array.isArray(field.hooks?.beforeDuplicate)) {
|
||||
if (fieldIsLocalized) {
|
||||
const localeData: JsonObject = {}
|
||||
|
||||
@@ -28,20 +28,20 @@ export async function buildFolderWhereConstraints({
|
||||
}),
|
||||
]
|
||||
|
||||
const baseFilterConstraint = await (
|
||||
collectionConfig.admin?.baseFilter ?? collectionConfig.admin?.baseListFilter
|
||||
)?.({
|
||||
limit: 0,
|
||||
locale: localeCode,
|
||||
page: 1,
|
||||
req,
|
||||
sort:
|
||||
sort ||
|
||||
(typeof collectionConfig.defaultSort === 'string' ? collectionConfig.defaultSort : 'id'),
|
||||
})
|
||||
if (typeof collectionConfig.admin?.baseListFilter === 'function') {
|
||||
const baseListFilterConstraint = await collectionConfig.admin.baseListFilter({
|
||||
limit: 0,
|
||||
locale: localeCode,
|
||||
page: 1,
|
||||
req,
|
||||
sort:
|
||||
sort ||
|
||||
(typeof collectionConfig.defaultSort === 'string' ? collectionConfig.defaultSort : 'id'),
|
||||
})
|
||||
|
||||
if (baseFilterConstraint) {
|
||||
constraints.push(baseFilterConstraint)
|
||||
if (baseListFilterConstraint) {
|
||||
constraints.push(baseListFilterConstraint)
|
||||
}
|
||||
}
|
||||
|
||||
if (folderID) {
|
||||
|
||||
@@ -873,7 +873,6 @@ export class BasePayload {
|
||||
this.config.jobs.scheduling
|
||||
) {
|
||||
await this.jobs.handleSchedules({
|
||||
allQueues: cronConfig.allQueues,
|
||||
queue: cronConfig.queue,
|
||||
})
|
||||
}
|
||||
@@ -892,7 +891,6 @@ export class BasePayload {
|
||||
}
|
||||
|
||||
await this.jobs.run({
|
||||
allQueues: cronConfig.allQueues,
|
||||
limit: cronConfig.limit ?? DEFAULT_LIMIT,
|
||||
queue: cronConfig.queue,
|
||||
silent: cronConfig.silent,
|
||||
@@ -1170,7 +1168,6 @@ export type {
|
||||
AfterRefreshHook as CollectionAfterRefreshHook,
|
||||
AuthCollection,
|
||||
AuthOperationsFromCollectionSlug,
|
||||
BaseFilter,
|
||||
BaseListFilter,
|
||||
BeforeChangeHook as CollectionBeforeChangeHook,
|
||||
BeforeDeleteHook as CollectionBeforeDeleteHook,
|
||||
|
||||
@@ -7,13 +7,6 @@ import type { TaskConfig } from './taskTypes.js'
|
||||
import type { WorkflowConfig } from './workflowTypes.js'
|
||||
|
||||
export type AutorunCronConfig = {
|
||||
/**
|
||||
* If you want to autoRUn jobs from all queues, set this to true.
|
||||
* If you set this to true, the `queue` property will be ignored.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
allQueues?: boolean
|
||||
/**
|
||||
* The cron schedule for the job.
|
||||
* @default '* * * * *' (every minute).
|
||||
@@ -50,8 +43,6 @@ export type AutorunCronConfig = {
|
||||
limit?: number
|
||||
/**
|
||||
* The queue name for the job.
|
||||
*
|
||||
* @default 'default'
|
||||
*/
|
||||
queue?: string
|
||||
/**
|
||||
|
||||
@@ -45,18 +45,11 @@ export const handleSchedulesJobsEndpoint: Endpoint = {
|
||||
)
|
||||
}
|
||||
|
||||
const { allQueues, queue } = req.query as {
|
||||
allQueues?: 'false' | 'true'
|
||||
const { queue } = req.query as {
|
||||
queue?: string
|
||||
}
|
||||
|
||||
const runAllQueues = allQueues && !(typeof allQueues === 'string' && allQueues === 'false')
|
||||
|
||||
const { errored, queued, skipped } = await handleSchedules({
|
||||
allQueues: runAllQueues,
|
||||
queue,
|
||||
req,
|
||||
})
|
||||
const { errored, queued, skipped } = await handleSchedules({ queue, req })
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
|
||||
@@ -56,7 +56,7 @@ export const runJobsEndpoint: Endpoint = {
|
||||
|
||||
if (shouldHandleSchedules && jobsConfig.scheduling) {
|
||||
// If should handle schedules and schedules are defined
|
||||
await req.payload.jobs.handleSchedules({ allQueues: runAllQueues, queue, req })
|
||||
await req.payload.jobs.handleSchedules({ queue: runAllQueues ? undefined : queue, req })
|
||||
}
|
||||
|
||||
const runJobsArgs: RunJobsArgs = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ObjectIdImport from 'bson-objectid'
|
||||
|
||||
import type { JobLog, PayloadRequest } from '../../index.js'
|
||||
import type { PayloadRequest } from '../../index.js'
|
||||
import type { RunJobsSilent } from '../localAPI.js'
|
||||
import type { UpdateJobFunction } from '../operations/runJobs/runJob/getUpdateJobFunction.js'
|
||||
import type { TaskError } from './index.js'
|
||||
@@ -60,6 +60,19 @@ export async function handleTaskError({
|
||||
|
||||
const currentDate = getCurrentDate()
|
||||
|
||||
;(job.log ??= []).push({
|
||||
id: new ObjectId().toHexString(),
|
||||
completedAt: currentDate.toISOString(),
|
||||
error: errorJSON,
|
||||
executedAt: executedAt.toISOString(),
|
||||
input,
|
||||
output: output ?? {},
|
||||
parent: req.payload.config.jobs.addParentToTaskLog ? parent : undefined,
|
||||
state: 'failed',
|
||||
taskID,
|
||||
taskSlug,
|
||||
})
|
||||
|
||||
if (job.waitUntil) {
|
||||
// Check if waitUntil is in the past
|
||||
const waitUntil = new Date(job.waitUntil)
|
||||
@@ -87,19 +100,6 @@ export async function handleTaskError({
|
||||
maxRetries = retriesConfig.attempts
|
||||
}
|
||||
|
||||
const taskLogToPush: JobLog = {
|
||||
id: new ObjectId().toHexString(),
|
||||
completedAt: currentDate.toISOString(),
|
||||
error: errorJSON,
|
||||
executedAt: executedAt.toISOString(),
|
||||
input,
|
||||
output: output ?? {},
|
||||
parent: req.payload.config.jobs.addParentToTaskLog ? parent : undefined,
|
||||
state: 'failed',
|
||||
taskID,
|
||||
taskSlug,
|
||||
}
|
||||
|
||||
if (!taskStatus?.complete && (taskStatus?.totalTried ?? 0) >= maxRetries) {
|
||||
/**
|
||||
* Task reached max retries => workflow will not retry
|
||||
@@ -108,9 +108,7 @@ export async function handleTaskError({
|
||||
await updateJob({
|
||||
error: errorJSON,
|
||||
hasError: true,
|
||||
log: {
|
||||
$push: taskLogToPush,
|
||||
} as any,
|
||||
log: job.log,
|
||||
processing: false,
|
||||
totalTried: (job.totalTried ?? 0) + 1,
|
||||
waitUntil: job.waitUntil,
|
||||
@@ -170,9 +168,7 @@ export async function handleTaskError({
|
||||
await updateJob({
|
||||
error: hasFinalError ? errorJSON : undefined,
|
||||
hasError: hasFinalError, // If reached max retries => final error. If hasError is true this job will not be retried
|
||||
log: {
|
||||
$push: taskLogToPush,
|
||||
} as any,
|
||||
log: job.log,
|
||||
processing: false,
|
||||
totalTried: (job.totalTried ?? 0) + 1,
|
||||
waitUntil: job.waitUntil,
|
||||
|
||||
@@ -79,6 +79,7 @@ export async function handleWorkflowError({
|
||||
await updateJob({
|
||||
error: errorJSON,
|
||||
hasError: hasFinalError, // If reached max retries => final error. If hasError is true this job will not be retried
|
||||
log: job.log,
|
||||
processing: false,
|
||||
totalTried: (job.totalTried ?? 0) + 1,
|
||||
waitUntil: job.waitUntil,
|
||||
|
||||
@@ -22,20 +22,13 @@ export type RunJobsSilent =
|
||||
| boolean
|
||||
export const getJobsLocalAPI = (payload: Payload) => ({
|
||||
handleSchedules: async (args?: {
|
||||
/**
|
||||
* If you want to schedule jobs from all queues, set this to true.
|
||||
* If you set this to true, the `queue` property will be ignored.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
allQueues?: boolean
|
||||
// By default, schedule all queues - only scheduling jobs scheduled to be added to the `default` queue would not make sense
|
||||
// here, as you'd usually specify a different queue than `default` here, especially if this is used in combination with autorun.
|
||||
// The `queue` property for setting up schedules is required, and not optional.
|
||||
/**
|
||||
* If you want to only schedule jobs that are set to schedule in a specific queue, set this to the queue name.
|
||||
*
|
||||
* @default jobs from the `default` queue will be executed.
|
||||
* @default all jobs for all queues will be scheduled.
|
||||
*/
|
||||
queue?: string
|
||||
req?: PayloadRequest
|
||||
@@ -43,7 +36,6 @@ export const getJobsLocalAPI = (payload: Payload) => ({
|
||||
const newReq: PayloadRequest = args?.req ?? (await createLocalReq({}, payload))
|
||||
|
||||
return await handleSchedules({
|
||||
allQueues: args?.allQueues,
|
||||
queue: args?.queue,
|
||||
req: newReq,
|
||||
})
|
||||
|
||||
@@ -23,26 +23,17 @@ export type HandleSchedulesResult = {
|
||||
* after they are scheduled
|
||||
*/
|
||||
export async function handleSchedules({
|
||||
allQueues = false,
|
||||
queue: _queue,
|
||||
queue,
|
||||
req,
|
||||
}: {
|
||||
/**
|
||||
* If you want to schedule jobs from all queues, set this to true.
|
||||
* If you set this to true, the `queue` property will be ignored.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
allQueues?: boolean
|
||||
/**
|
||||
* If you want to only schedule jobs that are set to schedule in a specific queue, set this to the queue name.
|
||||
*
|
||||
* @default jobs from the `default` queue will be executed.
|
||||
* @default all jobs for all queues will be scheduled.
|
||||
*/
|
||||
queue?: string
|
||||
req: PayloadRequest
|
||||
}): Promise<HandleSchedulesResult> {
|
||||
const queue = _queue ?? 'default'
|
||||
const jobsConfig = req.payload.config.jobs
|
||||
const queuesWithSchedules = getQueuesWithSchedules({
|
||||
jobsConfig,
|
||||
@@ -62,7 +53,7 @@ export async function handleSchedules({
|
||||
// Need to know when that particular job was last scheduled in that particular queue
|
||||
|
||||
for (const [queueName, { schedules }] of Object.entries(queuesWithSchedules)) {
|
||||
if (!allQueues && queueName !== queue) {
|
||||
if (queue && queueName !== queue) {
|
||||
// If a queue is specified, only schedule jobs for that queue
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import type {
|
||||
TaskType,
|
||||
} from '../../../config/types/taskTypes.js'
|
||||
import type {
|
||||
JobLog,
|
||||
SingleTaskStatus,
|
||||
WorkflowConfig,
|
||||
WorkflowTypes,
|
||||
@@ -186,7 +185,7 @@ export const getRunTaskFunction = <TIsInline extends boolean>(
|
||||
await taskConfig.onSuccess()
|
||||
}
|
||||
|
||||
const newLogItem: JobLog = {
|
||||
;(job.log ??= []).push({
|
||||
id: new ObjectId().toHexString(),
|
||||
completedAt: getCurrentDate().toISOString(),
|
||||
executedAt: executedAt.toISOString(),
|
||||
@@ -196,12 +195,10 @@ export const getRunTaskFunction = <TIsInline extends boolean>(
|
||||
state: 'succeeded',
|
||||
taskID,
|
||||
taskSlug,
|
||||
}
|
||||
})
|
||||
|
||||
await updateJob({
|
||||
log: {
|
||||
$push: newLogItem,
|
||||
} as any,
|
||||
log: job.log,
|
||||
})
|
||||
|
||||
return output
|
||||
|
||||
@@ -2,21 +2,21 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const zhTwTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-import-export': {
|
||||
allLocales: '所有語言地區',
|
||||
allLocales: '所有地區',
|
||||
exportDocumentLabel: '匯出 {{label}}',
|
||||
exportOptions: '匯出選項',
|
||||
'field-depth-label': '層級深度',
|
||||
'field-depth-label': '深度',
|
||||
'field-drafts-label': '包含草稿',
|
||||
'field-fields-label': '欄位',
|
||||
'field-format-label': '匯出格式',
|
||||
'field-limit-label': '筆數上限',
|
||||
'field-locale-label': '語言地區',
|
||||
'field-limit-label': '筆數限制',
|
||||
'field-locale-label': '語言/地區',
|
||||
'field-name-label': '檔案名稱',
|
||||
'field-selectionToUse-label': '使用的選取範圍',
|
||||
'field-selectionToUse-label': '選擇範圍',
|
||||
'field-sort-label': '排序方式',
|
||||
'selectionToUse-allDocuments': '使用所有文件',
|
||||
'selectionToUse-currentFilters': '使用目前篩選條件',
|
||||
'selectionToUse-currentSelection': '使用目前選取內容',
|
||||
'selectionToUse-currentSelection': '使用目前選擇',
|
||||
totalDocumentsCount: '共 {{count}} 筆文件',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
*/
|
||||
isGlobal?: boolean
|
||||
/**
|
||||
* Set to `false` if you want to manually apply the baseFilter
|
||||
* Set to `false` if you want to manually apply the baseListFilter
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
useBaseFilter?: boolean
|
||||
useBaseListFilter?: boolean
|
||||
/**
|
||||
* Set to `false` if you want to handle collection access manually without the multi-tenant constraints applied
|
||||
*
|
||||
|
||||
@@ -92,9 +92,7 @@ export const TenantSelector = ({ label, viewType }: { label: string; viewType?:
|
||||
<div className="tenant-selector">
|
||||
<SelectInput
|
||||
isClearable={viewType === 'list'}
|
||||
label={
|
||||
label ? getTranslation(label, i18n) : t('plugin-multi-tenant:nav-tenantSelector-label')
|
||||
}
|
||||
label={getTranslation(label, i18n)}
|
||||
name="setTenant"
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
@@ -112,7 +110,7 @@ export const TenantSelector = ({ label, viewType }: { label: string; viewType?:
|
||||
}}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
i18nKey="plugin-multi-tenant:confirm-modal-tenant-switch--body"
|
||||
i18nKey="plugin-multi-tenant:confirm-tenant-switch--body"
|
||||
t={t}
|
||||
variables={{
|
||||
fromTenant: selectedValue?.label,
|
||||
@@ -120,10 +118,8 @@ export const TenantSelector = ({ label, viewType }: { label: string; viewType?:
|
||||
}}
|
||||
/>
|
||||
}
|
||||
heading={t('plugin-multi-tenant:confirm-modal-tenant-switch--heading', {
|
||||
tenantLabel: label
|
||||
? getTranslation(label, i18n)
|
||||
: t('plugin-multi-tenant:nav-tenantSelector-label'),
|
||||
heading={t('plugin-multi-tenant:confirm-tenant-switch--heading', {
|
||||
tenantLabel: getTranslation(label, i18n),
|
||||
})}
|
||||
modalSlug={confirmSwitchTenantSlug}
|
||||
onConfirm={() => {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { tenantField } from '../fields/tenantField/index.js'
|
||||
export { tenantsArrayField } from '../fields/tenantsArrayField/index.js'
|
||||
|
||||
@@ -1,83 +1,65 @@
|
||||
import type { RelationshipFieldSingleValidation, SingleRelationshipField } from 'payload'
|
||||
|
||||
import { type RelationshipField } from 'payload'
|
||||
import { APIError } from 'payload'
|
||||
|
||||
import type { RootTenantFieldConfigOverrides } from '../../types.js'
|
||||
|
||||
import { defaults } from '../../defaults.js'
|
||||
import { getCollectionIDType } from '../../utilities/getCollectionIDType.js'
|
||||
import { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js'
|
||||
|
||||
type Args = {
|
||||
access?: RelationshipField['access']
|
||||
debug?: boolean
|
||||
name: string
|
||||
overrides?: RootTenantFieldConfigOverrides
|
||||
tenantsCollectionSlug: string
|
||||
unique: boolean
|
||||
}
|
||||
export const tenantField = ({
|
||||
name = defaults.tenantFieldName,
|
||||
access = undefined,
|
||||
debug,
|
||||
overrides: _overrides = {},
|
||||
tenantsCollectionSlug = defaults.tenantCollectionSlug,
|
||||
unique,
|
||||
}: Args): SingleRelationshipField => {
|
||||
const { validate, ...overrides } = _overrides || {}
|
||||
return {
|
||||
...(overrides || {}),
|
||||
name,
|
||||
type: 'relationship',
|
||||
access: overrides?.access || {},
|
||||
admin: {
|
||||
allowCreate: false,
|
||||
allowEdit: false,
|
||||
disableListColumn: true,
|
||||
disableListFilter: true,
|
||||
...(overrides?.admin || {}),
|
||||
components: {
|
||||
...(overrides?.admin?.components || {}),
|
||||
Field: {
|
||||
path: '@payloadcms/plugin-multi-tenant/client#TenantField',
|
||||
...(typeof overrides?.admin?.components?.Field !== 'string'
|
||||
? overrides?.admin?.components?.Field || {}
|
||||
: {}),
|
||||
clientProps: {
|
||||
...(typeof overrides?.admin?.components?.Field !== 'string'
|
||||
? (overrides?.admin?.components?.Field || {})?.clientProps
|
||||
: {}),
|
||||
debug,
|
||||
unique,
|
||||
},
|
||||
}: Args): RelationshipField => ({
|
||||
name,
|
||||
type: 'relationship',
|
||||
access,
|
||||
admin: {
|
||||
allowCreate: false,
|
||||
allowEdit: false,
|
||||
components: {
|
||||
Field: {
|
||||
clientProps: {
|
||||
debug,
|
||||
unique,
|
||||
},
|
||||
path: '@payloadcms/plugin-multi-tenant/client#TenantField',
|
||||
},
|
||||
},
|
||||
hasMany: false,
|
||||
hooks: {
|
||||
...(overrides.hooks || []),
|
||||
beforeChange: [
|
||||
({ req, value }) => {
|
||||
const idType = getCollectionIDType({
|
||||
collectionSlug: tenantsCollectionSlug,
|
||||
payload: req.payload,
|
||||
})
|
||||
if (!value) {
|
||||
const tenantFromCookie = getTenantFromCookie(req.headers, idType)
|
||||
if (tenantFromCookie) {
|
||||
return tenantFromCookie
|
||||
}
|
||||
throw new APIError('You must select a tenant', 400, null, true)
|
||||
disableListColumn: true,
|
||||
disableListFilter: true,
|
||||
},
|
||||
hasMany: false,
|
||||
hooks: {
|
||||
beforeChange: [
|
||||
({ req, value }) => {
|
||||
const idType = getCollectionIDType({
|
||||
collectionSlug: tenantsCollectionSlug,
|
||||
payload: req.payload,
|
||||
})
|
||||
if (!value) {
|
||||
const tenantFromCookie = getTenantFromCookie(req.headers, idType)
|
||||
if (tenantFromCookie) {
|
||||
return tenantFromCookie
|
||||
}
|
||||
throw new APIError('You must select a tenant', 400, null, true)
|
||||
}
|
||||
|
||||
return idType === 'number' ? parseFloat(value) : value
|
||||
},
|
||||
...(overrides?.hooks?.beforeChange || []),
|
||||
],
|
||||
},
|
||||
index: true,
|
||||
validate: (validate as RelationshipFieldSingleValidation) || undefined,
|
||||
// @ts-expect-error translations are not typed for this plugin
|
||||
label: overrides?.label || (({ t }) => t('plugin-multi-tenant:field-assignedTenant-label')),
|
||||
relationTo: tenantsCollectionSlug,
|
||||
unique,
|
||||
}
|
||||
}
|
||||
return idType === 'number' ? parseFloat(value) : value
|
||||
},
|
||||
],
|
||||
},
|
||||
index: true,
|
||||
// @ts-expect-error translations are not typed for this plugin
|
||||
label: ({ t }) => t('plugin-multi-tenant:field-assignedTentant-label'),
|
||||
relationTo: tenantsCollectionSlug,
|
||||
unique,
|
||||
})
|
||||
|
||||
@@ -15,7 +15,7 @@ import { addTenantCleanup } from './hooks/afterTenantDelete.js'
|
||||
import { translations } from './translations/index.js'
|
||||
import { addCollectionAccess } from './utilities/addCollectionAccess.js'
|
||||
import { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'
|
||||
import { combineFilters } from './utilities/combineFilters.js'
|
||||
import { combineListFilters } from './utilities/combineListFilters.js'
|
||||
|
||||
export const multiTenantPlugin =
|
||||
<ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) =>
|
||||
@@ -40,6 +40,7 @@ export const multiTenantPlugin =
|
||||
pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName
|
||||
const tenantsArrayTenantFieldName =
|
||||
pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName
|
||||
const tenantSelectorLabel = pluginConfig.tenantSelectorLabel || defaults.tenantSelectorLabel
|
||||
const basePath = pluginConfig.basePath || defaults.basePath
|
||||
|
||||
/**
|
||||
@@ -68,6 +69,37 @@ export const multiTenantPlugin =
|
||||
incomingConfig.collections = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tenant selector localized labels
|
||||
*/
|
||||
if (typeof tenantSelectorLabel === 'object') {
|
||||
if (!incomingConfig.i18n) {
|
||||
incomingConfig.i18n = {}
|
||||
}
|
||||
Object.entries(tenantSelectorLabel).forEach(([_locale, label]) => {
|
||||
const locale = _locale as AcceptedLanguages
|
||||
if (!incomingConfig.i18n) {
|
||||
incomingConfig.i18n = {}
|
||||
}
|
||||
if (!incomingConfig.i18n.translations) {
|
||||
incomingConfig.i18n.translations = {}
|
||||
}
|
||||
if (!(locale in incomingConfig.i18n.translations)) {
|
||||
incomingConfig.i18n.translations[locale] = {}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
if (!('multiTenant' in incomingConfig.i18n.translations[locale])) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
incomingConfig.i18n.translations[locale].multiTenant = {}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
incomingConfig.i18n.translations[locale].multiTenant.selectorLabel = label
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tenants array field to users collection
|
||||
*/
|
||||
@@ -111,10 +143,8 @@ export const multiTenantPlugin =
|
||||
adminUsersCollection.admin = {}
|
||||
}
|
||||
|
||||
const baseFilter =
|
||||
adminUsersCollection.admin?.baseFilter ?? adminUsersCollection.admin?.baseListFilter
|
||||
adminUsersCollection.admin.baseFilter = combineFilters({
|
||||
baseFilter,
|
||||
adminUsersCollection.admin.baseListFilter = combineListFilters({
|
||||
baseListFilter: adminUsersCollection.admin?.baseListFilter,
|
||||
customFilter: (args) =>
|
||||
filterDocumentsByTenants({
|
||||
filterFieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,
|
||||
@@ -177,9 +207,8 @@ export const multiTenantPlugin =
|
||||
collection.admin = {}
|
||||
}
|
||||
|
||||
const baseFilter = collection.admin?.baseFilter ?? collection.admin?.baseListFilter
|
||||
collection.admin.baseFilter = combineFilters({
|
||||
baseFilter,
|
||||
collection.admin.baseListFilter = combineListFilters({
|
||||
baseListFilter: collection.admin?.baseListFilter,
|
||||
customFilter: (args) =>
|
||||
filterDocumentsByTenants({
|
||||
filterFieldName: 'id',
|
||||
@@ -252,10 +281,6 @@ export const multiTenantPlugin =
|
||||
tenantsCollectionSlug,
|
||||
})
|
||||
|
||||
const overrides = pluginConfig.collections[collection.slug]?.tenantFieldOverrides
|
||||
? pluginConfig.collections[collection.slug]?.tenantFieldOverrides
|
||||
: pluginConfig.tenantField || {}
|
||||
|
||||
/**
|
||||
* Add tenant field to enabled collections
|
||||
*/
|
||||
@@ -263,17 +288,15 @@ export const multiTenantPlugin =
|
||||
0,
|
||||
0,
|
||||
tenantField({
|
||||
...(pluginConfig?.tenantField || {}),
|
||||
name: tenantFieldName,
|
||||
debug: pluginConfig.debug,
|
||||
overrides,
|
||||
tenantsCollectionSlug,
|
||||
unique: isGlobal,
|
||||
}),
|
||||
)
|
||||
|
||||
const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {}
|
||||
|
||||
if (useBaseFilter ?? useBaseListFilter ?? true) {
|
||||
if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {
|
||||
/**
|
||||
* Add list filter to enabled collections
|
||||
* - filters results by selected tenant
|
||||
@@ -282,9 +305,8 @@ export const multiTenantPlugin =
|
||||
collection.admin = {}
|
||||
}
|
||||
|
||||
const baseFilter = collection.admin?.baseFilter ?? collection.admin?.baseListFilter
|
||||
collection.admin.baseFilter = combineFilters({
|
||||
baseFilter,
|
||||
collection.admin.baseListFilter = combineListFilters({
|
||||
baseListFilter: collection.admin?.baseListFilter,
|
||||
customFilter: (args) =>
|
||||
filterDocumentsByTenants({
|
||||
filterFieldName: tenantFieldName,
|
||||
@@ -354,7 +376,7 @@ export const multiTenantPlugin =
|
||||
*/
|
||||
incomingConfig.admin.components.beforeNavLinks.push({
|
||||
clientProps: {
|
||||
label: pluginConfig.tenantSelectorLabel || undefined,
|
||||
label: tenantSelectorLabel,
|
||||
},
|
||||
path: '@payloadcms/plugin-multi-tenant/client#TenantSelector',
|
||||
})
|
||||
@@ -362,30 +384,22 @@ export const multiTenantPlugin =
|
||||
/**
|
||||
* Merge plugin translations
|
||||
*/
|
||||
if (!incomingConfig.i18n) {
|
||||
incomingConfig.i18n = {}
|
||||
}
|
||||
Object.entries(translations).forEach(([locale, pluginI18nObject]) => {
|
||||
const typedLocale = locale as AcceptedLanguages
|
||||
if (!incomingConfig.i18n!.translations) {
|
||||
incomingConfig.i18n!.translations = {}
|
||||
}
|
||||
if (!(typedLocale in incomingConfig.i18n!.translations)) {
|
||||
incomingConfig.i18n!.translations[typedLocale] = {}
|
||||
}
|
||||
if (!('plugin-multi-tenant' in incomingConfig.i18n!.translations[typedLocale]!)) {
|
||||
;(incomingConfig.i18n!.translations[typedLocale] as PluginDefaultTranslationsObject)[
|
||||
'plugin-multi-tenant'
|
||||
] = {} as PluginDefaultTranslationsObject['plugin-multi-tenant']
|
||||
}
|
||||
|
||||
;(incomingConfig.i18n!.translations[typedLocale] as PluginDefaultTranslationsObject)[
|
||||
'plugin-multi-tenant'
|
||||
] = {
|
||||
...pluginI18nObject.translations['plugin-multi-tenant'],
|
||||
...(pluginConfig.i18n?.translations?.[typedLocale] || {}),
|
||||
}
|
||||
})
|
||||
const simplifiedTranslations = Object.entries(translations).reduce(
|
||||
(acc, [key, value]) => {
|
||||
acc[key] = value.translations
|
||||
return acc
|
||||
},
|
||||
{} as Record<string, PluginDefaultTranslationsObject>,
|
||||
)
|
||||
|
||||
incomingConfig.i18n = {
|
||||
...incomingConfig.i18n,
|
||||
translations: deepMergeSimple(
|
||||
simplifiedTranslations,
|
||||
incomingConfig.i18n?.translations ?? {},
|
||||
),
|
||||
}
|
||||
|
||||
return incomingConfig
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const arTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'أنت على وشك تغيير الملكية من <0>{{fromTenant}}</0> إلى <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'تأكيد تغيير {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'المستأجر المعين',
|
||||
'nav-tenantSelector-label': 'المستأجر',
|
||||
'confirm-tenant-switch--heading': 'تأكيد تغيير {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'المستأجر المعين',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const azTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Siz <0>{{fromTenant}}</0>-dən <0>{{toTenant}}</0>-a mülkiyyəti dəyişməyə hazırlaşırsınız',
|
||||
'confirm-modal-tenant-switch--heading': '{{tenantLabel}} dəyişikliyini təsdiqləyin',
|
||||
'field-assignedTenant-label': 'Təyin edilmiş İcarəçi',
|
||||
'nav-tenantSelector-label': 'Kirayəçi',
|
||||
'confirm-tenant-switch--body':
|
||||
'Siz <0>{{fromTenant}}</0> mülkiyyətini <0>{{toTenant}}</0> mülkiyyətinə dəyişdirəcəksiniz.',
|
||||
'confirm-tenant-switch--heading': '{{tenantLabel}} dəyişikliyini təsdiqləyin',
|
||||
'field-assignedTentant-label': 'Təyin edilmiş İcarəçi',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const bgTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Предстои да промените собствеността от <0>{{fromTenant}}</0> на <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Потвърждаване на промяна в {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Назначен наемател',
|
||||
'nav-tenantSelector-label': 'Потребител',
|
||||
'confirm-tenant-switch--heading': 'Потвърдете промяната на {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Назначен наемател',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.js'
|
||||
|
||||
export const bnBdTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'আপনি <0>{{fromTenant}}</0> থেকে <0>{{toTenant}}</0> তে মালিকানা পরিবর্তন করতে চলেছেন।',
|
||||
'confirm-modal-tenant-switch--heading': '{{tenantLabel}} পরিবর্তন নিশ্চিত করুন',
|
||||
'field-assignedTenant-label': 'নির্ধারিত টেনেন্ট',
|
||||
'nav-tenantSelector-label': 'ভাড়াটিয়া',
|
||||
},
|
||||
}
|
||||
|
||||
export const bnBd: PluginLanguage = {
|
||||
dateFNSKey: 'bn-BD',
|
||||
translations: bnBdTranslations,
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.js'
|
||||
|
||||
export const bnInTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'আপনি স্বত্বাধিকার পরিবর্তন করতে চলেছেন <0>{{fromTenant}}</0> থেকে <0>{{toTenant}}</0> এ।',
|
||||
'confirm-modal-tenant-switch--heading': '{{tenantLabel}} পরিবর্তন নিশ্চিত করুন',
|
||||
'field-assignedTenant-label': 'নির্ধারিত টেনেন্ট',
|
||||
'nav-tenantSelector-label': 'ভাড়াটিয়া',
|
||||
},
|
||||
}
|
||||
|
||||
export const bnIn: PluginLanguage = {
|
||||
dateFNSKey: 'bn-IN',
|
||||
translations: bnInTranslations,
|
||||
}
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const caTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Està a punt de canviar la propietat de <0>{{fromTenant}}</0> a <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Confirmeu el canvi de {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Llogater Assignat',
|
||||
'nav-tenantSelector-label': 'Inquilí',
|
||||
'confirm-tenant-switch--body':
|
||||
'Estàs a punt de canviar la propietat de <0>{{fromTenant}}</0> a <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Confirmeu el canvi de {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Llogater Assignat',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const csTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Chystáte se změnit vlastnictví z <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potvrďte změnu {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Přiřazený nájemce',
|
||||
'nav-tenantSelector-label': 'Nájemce',
|
||||
'confirm-tenant-switch--heading': 'Potvrďte změnu {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Přiřazený nájemce',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const daTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Du er ved at skifte ejerskab fra <0>{{fromTenant}}</0> til <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Bekræft ændring af {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Tildelt Lejer',
|
||||
'nav-tenantSelector-label': 'Lejer',
|
||||
'confirm-tenant-switch--body':
|
||||
'Du er ved at ændre ejerskab fra <0>{{fromTenant}}</0> til <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Bekræft {{tenantLabel}} ændring',
|
||||
'field-assignedTentant-label': 'Tildelt Lejer',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const deTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Sie sind dabei, den Besitz von <0>{{fromTenant}}</0> zu <0>{{toTenant}}</0> zu ändern.',
|
||||
'confirm-modal-tenant-switch--heading': 'Bestätigung der Änderung von {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Zugewiesener Mandant',
|
||||
'nav-tenantSelector-label': 'Mieter',
|
||||
'confirm-tenant-switch--body':
|
||||
'Sie sind dabei, den Besitz von <0>{{fromTenant}}</0> auf <0>{{toTenant}}</0> zu übertragen.',
|
||||
'confirm-tenant-switch--heading': 'Bestätigen Sie die Änderung von {{tenantLabel}}.',
|
||||
'field-assignedTentant-label': 'Zugewiesener Mandant',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginLanguage } from '../types.js'
|
||||
|
||||
export const enTranslations = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'You are about to change ownership from <0>{{fromTenant}}</0> to <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Confirm {{tenantLabel}} change',
|
||||
'field-assignedTenant-label': 'Assigned Tenant',
|
||||
'nav-tenantSelector-label': 'Tenant',
|
||||
'confirm-tenant-switch--heading': 'Confirm {{tenantLabel}} change',
|
||||
'field-assignedTentant-label': 'Assigned Tenant',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const esTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Está a punto de cambiar la propiedad de <0>{{fromTenant}}</0> a <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Confirme el cambio de {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Inquilino Asignado',
|
||||
'nav-tenantSelector-label': 'Inquilino',
|
||||
'confirm-tenant-switch--heading': 'Confirme el cambio de {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Inquilino Asignado',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const etTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Te olete just muutmas omandiõigust <0>{{fromTenant}}</0> -lt <0>{{toTenant}}</0> -le.',
|
||||
'confirm-modal-tenant-switch--heading': 'Kinnita {{tenantLabel}} muutus',
|
||||
'field-assignedTenant-label': 'Määratud üürnik',
|
||||
'nav-tenantSelector-label': 'Üürnik',
|
||||
'confirm-tenant-switch--body':
|
||||
'Te olete tegemas omandiõiguse muudatust <0>{{fromTenant}}</0>lt <0>{{toTenant}}</0>le.',
|
||||
'confirm-tenant-switch--heading': 'Kinnita {{tenantLabel}} muutus',
|
||||
'field-assignedTentant-label': 'Määratud üürnik',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const faTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'شما در حال تغییر مالکیت از <0>{{fromTenant}}</0> به <0>{{toTenant}}</0> هستید.',
|
||||
'confirm-modal-tenant-switch--heading': 'تأیید تغییر {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'مستاجر اختصاص یافته',
|
||||
'nav-tenantSelector-label': 'مستاجر',
|
||||
'confirm-tenant-switch--body':
|
||||
'شما در حال تغییر مالکیت از <0>{{fromTenant}}</0> به <0>{{toTenant}}</0> هستید',
|
||||
'confirm-tenant-switch--heading': 'تایید تغییر {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'مستاجر اختصاص یافته',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const frTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Vous êtes sur le point de changer la propriété de <0>{{fromTenant}}</0> à <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Confirmer le changement de {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Locataire Attribué',
|
||||
'nav-tenantSelector-label': 'Locataire',
|
||||
'confirm-tenant-switch--heading': 'Confirmer le changement de {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Locataire Attribué',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const heTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'אתה עומד לשנות בעלות מ- <0>{{fromTenant}}</0> ל- <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'אשר שינוי {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'דייר מוקצה',
|
||||
'nav-tenantSelector-label': 'דייר',
|
||||
'confirm-tenant-switch--heading': 'אשר שינוי {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'דייר מוקצה',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const hrTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Na rubu ste promjene vlasništva iz <0>{{fromTenant}}</0> u <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potvrdite promjenu {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Dodijeljeni stanar',
|
||||
'nav-tenantSelector-label': 'Podstanar',
|
||||
'confirm-tenant-switch--body':
|
||||
'Upravo ćete promijeniti vlasništvo sa <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Potvrdi promjenu {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Dodijeljeni stanar',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const huTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Közel áll ahhoz, hogy megváltoztassa a tulajdonságot <0>{{fromTenant}}</0> -ból <0>{{toTenant}}</0> -ba.',
|
||||
'confirm-modal-tenant-switch--heading': 'Erősítse meg a {{tenantLabel}} változást',
|
||||
'field-assignedTenant-label': 'Kijelölt Bérlő',
|
||||
'nav-tenantSelector-label': 'Bérlő',
|
||||
'confirm-tenant-switch--body':
|
||||
'Ön azon van, hogy megváltoztassa a tulajdonjogot <0>{{fromTenant}}</0>-ről <0>{{toTenant}}</0>-re.',
|
||||
'confirm-tenant-switch--heading': 'Erősítse meg a(z) {{tenantLabel}} változtatást',
|
||||
'field-assignedTentant-label': 'Kijelölt Bérlő',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const hyTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Դուք պատրաստվում եք փոխել սեփականությունը <0>{{fromTenant}}</0>-ից <0>{{toTenant}}</0>-ին:',
|
||||
'confirm-modal-tenant-switch--heading': 'Հաստատեք {{tenantLabel}}֊ի փոփոխությունը',
|
||||
'field-assignedTenant-label': 'Հանձնարարված վարձակալ',
|
||||
'nav-tenantSelector-label': 'Տենանտ',
|
||||
'confirm-tenant-switch--body':
|
||||
'Դուք պատրաստ եք փոխել գերեցդիմատնին ընկերությունը <0>{{fromTenant}}</0>-ից <0>{{toTenant}}</0>-ին',
|
||||
'confirm-tenant-switch--heading': 'Հաստատեք {{tenantLabel}} փոփոխությունը',
|
||||
'field-assignedTentant-label': 'Հանձնարարված վարձակալ',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.js'
|
||||
|
||||
export const idTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Anda akan mengubah kepemilikan dari <0>{{fromTenant}}</0> ke <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Konfirmasi perubahan {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Penyewa yang Ditugaskan',
|
||||
'nav-tenantSelector-label': 'Penyewa',
|
||||
},
|
||||
}
|
||||
|
||||
export const id: PluginLanguage = {
|
||||
dateFNSKey: 'id',
|
||||
translations: idTranslations,
|
||||
}
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const itTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Stai per cambiare il possesso da <0>{{fromTenant}}</0> a <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Conferma il cambiamento di {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Inquilino Assegnato',
|
||||
'nav-tenantSelector-label': 'Inquilino',
|
||||
'confirm-tenant-switch--body':
|
||||
'Stai per cambiare proprietà da <0>{{fromTenant}}</0> a <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Conferma il cambiamento di {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Inquilino Assegnato',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const jaTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'あなたは、<0>{{fromTenant}}</0>から<0>{{toTenant}}</0>への所有権を変更しようとしています。',
|
||||
'confirm-modal-tenant-switch--heading': '{{tenantLabel}}の変更を確認します',
|
||||
'field-assignedTenant-label': '割り当てられたテナント',
|
||||
'nav-tenantSelector-label': 'テナント',
|
||||
'confirm-tenant-switch--body':
|
||||
'あなたは所有権を<0>{{fromTenant}}</0>から<0>{{toTenant}}</0>へ変更しようとしています',
|
||||
'confirm-tenant-switch--heading': '{{tenantLabel}}の変更を確認してください',
|
||||
'field-assignedTentant-label': '割り当てられたテナント',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const koTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'<0>{{fromTenant}}</0>에서 <0>{{toTenant}}</0>로 소유권을 변경하려고 합니다.',
|
||||
'confirm-modal-tenant-switch--heading': '{{tenantLabel}} 변경 확인',
|
||||
'field-assignedTenant-label': '지정된 세입자',
|
||||
'nav-tenantSelector-label': '세입자',
|
||||
'confirm-tenant-switch--body':
|
||||
'<0>{{fromTenant}}</0>에서 <0>{{toTenant}}</0>으로 소유권을 변경하려고 합니다.',
|
||||
'confirm-tenant-switch--heading': '{{tenantLabel}} 변경을 확인하세요',
|
||||
'field-assignedTentant-label': '지정된 세입자',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const ltTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Jūs ketinate pakeisti nuosavybę iš <0>{{fromTenant}}</0> į <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Patvirtinkite {{tenantLabel}} pakeitimą',
|
||||
'field-assignedTenant-label': 'Paskirtas nuomininkas',
|
||||
'nav-tenantSelector-label': 'Nuomininkas',
|
||||
'confirm-tenant-switch--body':
|
||||
'Jūs ketinate pakeisti nuosavybės teisę iš <0>{{fromTenant}}</0> į <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Patvirtinkite {{tenantLabel}} pakeitimą',
|
||||
'field-assignedTentant-label': 'Paskirtas nuomininkas',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const lvTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Jūs gatavojaties mainīt īpašumtiesības no <0>{{fromTenant}}</0> uz <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Apstipriniet {{tenantLabel}} izmaiņu',
|
||||
'field-assignedTenant-label': 'Piešķirts nomnieks',
|
||||
'nav-tenantSelector-label': 'Nomnieks',
|
||||
'confirm-tenant-switch--heading': 'Apstipriniet {{tenantLabel}} izmaiņu',
|
||||
'field-assignedTentant-label': 'Piešķirts īrnieks',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const myTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Anda akan menukar pemilikan dari <0>{{fromTenant}}</0> kepada <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Sahkan perubahan {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'ခွဲစိုက်ထားသော အငှားယူသူ',
|
||||
'nav-tenantSelector-label': 'Penyewa',
|
||||
'confirm-tenant-switch--body':
|
||||
'Anda akan mengubah pemilikan dari <0>{{fromTenant}}</0> ke <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Sahkan perubahan {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'ခွဲစိုက်ထားသော အငှားယူသူ',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const nbTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Du er i ferd med å endre eierskap fra <0>{{fromTenant}}</0> til <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Bekreft endring av {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Tildelt leietaker',
|
||||
'nav-tenantSelector-label': 'Leietaker',
|
||||
'confirm-tenant-switch--heading': 'Bekreft {{tenantLabel}} endring',
|
||||
'field-assignedTentant-label': 'Tildelt leietaker',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const nlTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'U staat op het punt om eigenaarschap te wijzigen van <0>{{fromTenant}}</0> naar <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Bevestig wijziging van {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Toegewezen Huurder',
|
||||
'nav-tenantSelector-label': 'Huurder',
|
||||
'confirm-tenant-switch--body':
|
||||
'U staat op het punt het eigendom te wijzigen van <0>{{fromTenant}}</0> naar <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Bevestig wijziging van {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Toegewezen Huurder',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const plTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Za chwilę nastąpi zmiana właściciela z <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potwierdź zmianę {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Przypisany Najemca',
|
||||
'nav-tenantSelector-label': 'Najemca',
|
||||
'confirm-tenant-switch--heading': 'Potwierdź zmianę {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Przypisany Najemca',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const ptTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Está prestes a mudar a propriedade de <0>{{fromTenant}}</0> para <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Confirme a alteração do {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Inquilino Atribuído',
|
||||
'nav-tenantSelector-label': 'Inquilino',
|
||||
'confirm-tenant-switch--body':
|
||||
'Você está prestes a alterar a propriedade de <0>{{fromTenant}}</0> para <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Confirme a alteração de {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Inquilino Atribuído',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const roTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Sunteți pe cale să schimbați proprietatea de la <0>{{fromTenant}}</0> la <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Confirmați modificarea {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Locatar Atribuit',
|
||||
'nav-tenantSelector-label': 'Locatar',
|
||||
'confirm-tenant-switch--body':
|
||||
'Sunteți pe punctul de a schimba proprietatea de la <0>{{fromTenant}}</0> la <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Confirmați schimbarea {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Locatar Atribuit',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const rsTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Na putu ste da promenite vlasništvo od <0>{{fromTenant}}</0> do <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potvrdite promenu {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Dodeljen stanar',
|
||||
'nav-tenantSelector-label': 'Podstanar',
|
||||
'confirm-tenant-switch--body':
|
||||
'Upravo ćete promeniti vlasništvo sa <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Potvrdi promena {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Dodeljen stanar',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const rsLatinTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Uskoro ćete promeniti vlasništvo sa <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potvrdite promenu {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Dodeljen stanar',
|
||||
'nav-tenantSelector-label': 'Podstanar',
|
||||
'confirm-tenant-switch--heading': 'Potvrdite promenu {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Dodeljen stanar',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const ruTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Вы собираетесь изменить владельца с <0>{{fromTenant}}</0> на <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Подтвердите изменение {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Назначенный Арендатор',
|
||||
'nav-tenantSelector-label': 'Арендатор',
|
||||
'confirm-tenant-switch--heading': 'Подтвердите изменение {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Назначенный Арендатор',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const skTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'confirm-tenant-switch--body':
|
||||
'Chystáte sa zmeniť vlastníctvo z <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potvrďte zmenu {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Pridelený nájomca',
|
||||
'nav-tenantSelector-label': 'Nájomca',
|
||||
'confirm-tenant-switch--heading': 'Potvrďte zmenu {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Pridelený nájomca',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const slTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Pravkar ste na točki, da spremenite lastništvo iz <0>{{fromTenant}}</0> v <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Potrdite spremembo {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Dodeljen najemnik',
|
||||
'nav-tenantSelector-label': 'Najemnik',
|
||||
'confirm-tenant-switch--body':
|
||||
'Ravno ste pred spremembo lastništva iz <0>{{fromTenant}}</0> na <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Potrdi spremembo {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Dodeljen najemnik',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const svTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Du är på väg att ändra ägande från <0>{{fromTenant}}</0> till <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Bekräfta ändring av {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Tilldelad hyresgäst',
|
||||
'nav-tenantSelector-label': 'Hyresgäst',
|
||||
'confirm-tenant-switch--body':
|
||||
'Du är på väg att ändra ägare från <0>{{fromTenant}}</0> till <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Bekräfta ändring av {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Tilldelad hyresgäst',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const thTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'คุณกำลังจะเปลี่ยนสิทธิ์การเป็นเจ้าของจาก <0>{{fromTenant}}</0> ไปยัง <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'ยืนยันการเปลี่ยนแปลง {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'ผู้เช่าที่ได้รับการกำหนด',
|
||||
'nav-tenantSelector-label': 'ผู้เช่า',
|
||||
'confirm-tenant-switch--body':
|
||||
'คุณกำลังจะเปลี่ยนความเป็นเจ้าของจาก <0>{{fromTenant}}</0> เป็น <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'ยืนยันการเปลี่ยนแปลง {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'ผู้เช่าที่ได้รับการกำหนด',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const trTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
"<0>{{fromTenant}}</0>'den <0>{{toTenant}}</0>'ye sahipliği değiştirmek üzeresiniz.",
|
||||
'confirm-modal-tenant-switch--heading': '{{tenantLabel}} değişikliğini onayla',
|
||||
'field-assignedTenant-label': 'Atanan Kiracı',
|
||||
'nav-tenantSelector-label': 'Kiracı',
|
||||
'confirm-tenant-switch--body':
|
||||
"Sahipliği <0>{{fromTenant}}</0>'den <0>{{toTenant}}</0>'e değiştirmek üzeresiniz.",
|
||||
'confirm-tenant-switch--heading': '{{tenantLabel}} değişikliğini onayla',
|
||||
'field-assignedTentant-label': 'Atanan Kiracı',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const ukTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Ви збираєтеся змінити власність з <0>{{fromTenant}}</0> на <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Підтвердіть зміну {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Призначений орендар',
|
||||
'nav-tenantSelector-label': 'Орендар',
|
||||
'confirm-tenant-switch--body':
|
||||
'Ви збираєтесь змінити власність з <0>{{fromTenant}}</0> на <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Підтвердіть зміну {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Призначений орендар',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const viTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'Bạn sắp chuyển quyền sở hữu từ <0>{{fromTenant}}</0> đến <0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': 'Xác nhận thay đổi {{tenantLabel}}',
|
||||
'field-assignedTenant-label': 'Người thuê đã được chỉ định',
|
||||
'nav-tenantSelector-label': 'Người thuê',
|
||||
'confirm-tenant-switch--body':
|
||||
'Bạn đang chuẩn bị chuyển quyền sở hữu từ <0>{{fromTenant}}</0> sang <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': 'Xác nhận thay đổi {{tenantLabel}}',
|
||||
'field-assignedTentant-label': 'Người thuê đã được chỉ định',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,9 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const zhTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'您即将从<0>{{fromTenant}}</0>更改为<0>{{toTenant}}</0>的所有权',
|
||||
'confirm-modal-tenant-switch--heading': '确认更改{{tenantLabel}}',
|
||||
'field-assignedTenant-label': '指定租户',
|
||||
'nav-tenantSelector-label': '租户',
|
||||
'confirm-tenant-switch--body': '您即将将所有权从<0>{{fromTenant}}</0>更改为<0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': '确认更改{{tenantLabel}}',
|
||||
'field-assignedTentant-label': '指定租户',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import type { PluginDefaultTranslationsObject, PluginLanguage } from '../types.j
|
||||
|
||||
export const zhTwTranslations: PluginDefaultTranslationsObject = {
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body':
|
||||
'您即將從<0>{{fromTenant}}</0>變更所有權至<0>{{toTenant}}</0>',
|
||||
'confirm-modal-tenant-switch--heading': '確認變更 {{tenantLabel}}',
|
||||
'field-assignedTenant-label': '指派的租用戶',
|
||||
'nav-tenantSelector-label': '租戶',
|
||||
'confirm-tenant-switch--body':
|
||||
'您即將將所有權從 <0>{{fromTenant}}</0> 轉移至 <0>{{toTenant}}</0>',
|
||||
'confirm-tenant-switch--heading': '確認{{tenantLabel}}更改',
|
||||
'field-assignedTentant-label': '指定的租戶',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@ import type { enTranslations } from './languages/en.js'
|
||||
|
||||
export type PluginLanguage = Language<{
|
||||
'plugin-multi-tenant': {
|
||||
'confirm-modal-tenant-switch--body': string
|
||||
'confirm-modal-tenant-switch--heading': string
|
||||
'field-assignedTenant-label': string
|
||||
'nav-tenantSelector-label': string
|
||||
'confirm-tenant-switch--body': string
|
||||
'confirm-tenant-switch--heading': string
|
||||
'field-assignedTentant-label': string
|
||||
}
|
||||
}>
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
import type { AcceptedLanguages } from '@payloadcms/translations'
|
||||
import type {
|
||||
ArrayField,
|
||||
CollectionSlug,
|
||||
Field,
|
||||
RelationshipField,
|
||||
SingleRelationshipField,
|
||||
TypedUser,
|
||||
} from 'payload'
|
||||
import type { ArrayField, CollectionSlug, Field, RelationshipField, TypedUser } from 'payload'
|
||||
|
||||
export type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
/**
|
||||
@@ -36,25 +29,8 @@ export type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
* @default false
|
||||
*/
|
||||
isGlobal?: boolean
|
||||
/**
|
||||
* Overrides for the tenant field, will override the entire tenantField configuration
|
||||
*/
|
||||
tenantFieldOverrides?: CollectionTenantFieldConfigOverrides
|
||||
/**
|
||||
* Set to `false` if you want to manually apply the baseListFilter
|
||||
* Set to `false` if you want to manually apply the baseFilter
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
useBaseFilter?: boolean
|
||||
/**
|
||||
* @deprecated Use `useBaseFilter` instead. If both are defined,
|
||||
* `useBaseFilter` will take precedence. This property remains only
|
||||
* for backward compatibility and may be removed in a future version.
|
||||
*
|
||||
* Originally, `baseListFilter` was intended to filter only the List View
|
||||
* in the admin panel. However, base filtering is often required in other areas
|
||||
* such as internal link relationships in the Lexical editor.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
@@ -80,37 +56,18 @@ export type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
* @default true
|
||||
*/
|
||||
enabled?: boolean
|
||||
/**
|
||||
* Localization for the plugin
|
||||
*/
|
||||
i18n?: {
|
||||
translations: {
|
||||
[key in AcceptedLanguages]?: {
|
||||
/**
|
||||
* @default 'You are about to change ownership from <0>{{fromTenant}}</0> to <0>{{toTenant}}</0>'
|
||||
*/
|
||||
'confirm-modal-tenant-switch--body'?: string
|
||||
/**
|
||||
* `tenantLabel` defaults to the value of the `nav-tenantSelector-label` translation
|
||||
*
|
||||
* @default 'Confirm {{tenantLabel}} change'
|
||||
*/
|
||||
'confirm-modal-tenant-switch--heading'?: string
|
||||
/**
|
||||
* @default 'Assigned Tenant'
|
||||
*/
|
||||
'field-assignedTenant-label'?: string
|
||||
/**
|
||||
* @default 'Tenant'
|
||||
*/
|
||||
'nav-tenantSelector-label'?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Field configuration for the field added to all tenant enabled collections
|
||||
*/
|
||||
tenantField?: RootTenantFieldConfigOverrides
|
||||
tenantField?: {
|
||||
access?: RelationshipField['access']
|
||||
/**
|
||||
* The name of the field added to all tenant enabled collections
|
||||
*
|
||||
* @default 'tenant'
|
||||
*/
|
||||
name?: string
|
||||
}
|
||||
/**
|
||||
* Field configuration for the field added to the users collection
|
||||
*
|
||||
@@ -163,8 +120,6 @@ export type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
* Customize tenant selector label
|
||||
*
|
||||
* Either a string or an object where the keys are i18n codes and the values are the string labels
|
||||
*
|
||||
* @deprecated Use `i18n.translations` instead.
|
||||
*/
|
||||
tenantSelectorLabel?:
|
||||
| Partial<{
|
||||
@@ -199,30 +154,6 @@ export type MultiTenantPluginConfig<ConfigTypes = unknown> = {
|
||||
useUsersTenantFilter?: boolean
|
||||
}
|
||||
|
||||
export type RootTenantFieldConfigOverrides = Partial<
|
||||
Omit<
|
||||
SingleRelationshipField,
|
||||
| '_sanitized'
|
||||
| 'hasMany'
|
||||
| 'hidden'
|
||||
| 'index'
|
||||
| 'localized'
|
||||
| 'max'
|
||||
| 'maxRows'
|
||||
| 'min'
|
||||
| 'minRows'
|
||||
| 'relationTo'
|
||||
| 'required'
|
||||
| 'type'
|
||||
| 'unique'
|
||||
| 'virtual'
|
||||
>
|
||||
>
|
||||
|
||||
export type CollectionTenantFieldConfigOverrides = Partial<
|
||||
Omit<RootTenantFieldConfigOverrides, 'name'>
|
||||
>
|
||||
|
||||
export type Tenant<IDType = number | string> = {
|
||||
id: IDType
|
||||
name: string
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import type { BaseFilter, Where } from 'payload'
|
||||
import type { BaseListFilter, Where } from 'payload'
|
||||
|
||||
type Args = {
|
||||
baseFilter?: BaseFilter
|
||||
customFilter: BaseFilter
|
||||
baseListFilter?: BaseListFilter
|
||||
customFilter: BaseListFilter
|
||||
}
|
||||
/**
|
||||
* Combines a base filter with a tenant list filter
|
||||
* Combines a base list filter with a tenant list filter
|
||||
*
|
||||
* Combines where constraints inside of an AND operator
|
||||
*/
|
||||
export const combineFilters =
|
||||
({ baseFilter, customFilter }: Args): BaseFilter =>
|
||||
export const combineListFilters =
|
||||
({ baseListFilter, customFilter }: Args): BaseListFilter =>
|
||||
async (args) => {
|
||||
const filterConstraints = []
|
||||
|
||||
if (typeof baseFilter === 'function') {
|
||||
const baseFilterResult = await baseFilter(args)
|
||||
if (typeof baseListFilter === 'function') {
|
||||
const baseListFilterResult = await baseListFilter(args)
|
||||
|
||||
if (baseFilterResult) {
|
||||
filterConstraints.push(baseFilterResult)
|
||||
if (baseListFilterResult) {
|
||||
filterConstraints.push(baseListFilterResult)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,24 +4,24 @@ export const zhTw: GenericTranslationsObject = {
|
||||
$schema: './translation-schema.json',
|
||||
'plugin-seo': {
|
||||
almostThere: '快完成了',
|
||||
autoGenerate: '自動產生',
|
||||
bestPractices: '最佳做法',
|
||||
characterCount: '{{current}}/{{minLength}}-{{maxLength}} 字元,',
|
||||
charactersLeftOver: '多出 {{characters}} 個字元',
|
||||
charactersToGo: '還差 {{characters}} 個字元',
|
||||
charactersTooMany: '超出 {{characters}} 個字元',
|
||||
checksPassing: '{{current}} 項檢查通過,共 {{max}} 項',
|
||||
good: '良好',
|
||||
imageAutoGenerationTip: '系統會自動擷取選取的主圖。',
|
||||
autoGenerate: '自動生成',
|
||||
bestPractices: '最佳實踐',
|
||||
characterCount: '{{current}}/{{minLength}}-{{maxLength}} 字符, ',
|
||||
charactersLeftOver: '{{characters}} 字符剩餘',
|
||||
charactersToGo: '{{characters}} 字符待輸入',
|
||||
charactersTooMany: '{{characters}} 字符太多',
|
||||
checksPassing: '{{current}}/{{max}} 檢查通過',
|
||||
good: '好',
|
||||
imageAutoGenerationTip: '自動生成將獲取選定的主圖像。',
|
||||
lengthTipDescription:
|
||||
'長度應介於 {{minLength}} 到 {{maxLength}} 個字元。若需撰寫高品質後設資料描述的協助,請參閱',
|
||||
'此文本應介於 {{minLength}} 和 {{maxLength}} 個字符之間。如需有關編寫高質量 meta 描述的幫助,請參見 ',
|
||||
lengthTipTitle:
|
||||
'長度應介於 {{minLength}} 到 {{maxLength}} 個字元。若需撰寫高品質後設資料標題的協助,請參閱',
|
||||
missing: '尚未設定',
|
||||
'此文本應介於 {{minLength}} 和 {{maxLength}} 個字符之間。如需有關編寫高質量 meta 標題的幫助,請參見 ',
|
||||
missing: '缺失',
|
||||
noImage: '沒有圖片',
|
||||
preview: '預覽',
|
||||
previewDescription: '實際搜尋結果可能會因內容與關聯性而有所不同。',
|
||||
tooLong: '過長',
|
||||
tooShort: '過短',
|
||||
previewDescription: '實際搜尋結果可能會根據內容和搜尋相關性有所不同。',
|
||||
tooLong: '太長',
|
||||
tooShort: '太短',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -117,23 +117,13 @@ export const getBaseFields = (
|
||||
type: 'relationship',
|
||||
filterOptions:
|
||||
!enabledCollections && !disabledCollections
|
||||
? async ({ relationTo, req, user }) => {
|
||||
const admin = config.collections.find(({ slug }) => slug === relationTo)?.admin
|
||||
|
||||
const hidden = admin?.hidden
|
||||
? ({ relationTo, user }) => {
|
||||
const hidden = config.collections.find(({ slug }) => slug === relationTo)?.admin
|
||||
.hidden
|
||||
if (typeof hidden === 'function' && hidden({ user } as { user: TypedUser })) {
|
||||
return false
|
||||
}
|
||||
|
||||
const baseFilter = admin?.baseFilter ?? admin?.baseListFilter
|
||||
return (
|
||||
(await baseFilter?.({
|
||||
limit: 0,
|
||||
page: 1,
|
||||
req,
|
||||
sort: 'id',
|
||||
})) ?? true
|
||||
)
|
||||
return true
|
||||
}
|
||||
: null,
|
||||
label: ({ t }) => t('fields:chooseDocumentToLink'),
|
||||
|
||||
@@ -124,7 +124,7 @@ export function convertTextNode(node: SlateNode): SerializedTextNode {
|
||||
format: convertNodeToFormat(node),
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: node.text ?? '',
|
||||
text: node.text ?? "",
|
||||
version: 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,6 @@ export const clientTranslationKeys = createClientTranslationKeys([
|
||||
'general:deleted',
|
||||
'general:deletedAt',
|
||||
'general:deletePermanently',
|
||||
'general:deleteLabel',
|
||||
'general:deletedSuccessfully',
|
||||
'general:deletedCountSuccessfully',
|
||||
'general:deleting',
|
||||
@@ -275,7 +274,6 @@ export const clientTranslationKeys = createClientTranslationKeys([
|
||||
'general:movingCount',
|
||||
'general:name',
|
||||
'general:next',
|
||||
'general:newLabel',
|
||||
'general:noDateSelected',
|
||||
'general:noFiltersSet',
|
||||
'general:noLabel',
|
||||
|
||||
@@ -276,7 +276,6 @@ export const arTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'تم الحذف في',
|
||||
deletedCountSuccessfully: 'تمّ حذف {{count}} {{label}} بنجاح.',
|
||||
deletedSuccessfully: 'تمّ الحذف بنجاح.',
|
||||
deleteLabel: 'احذف {{label}}',
|
||||
deletePermanently: 'تجاوز السلة واحذف بشكل دائم',
|
||||
deleting: 'يتمّ الحذف...',
|
||||
depth: 'عمق',
|
||||
@@ -336,7 +335,6 @@ export const arTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'التّحريك إلى الأعلى',
|
||||
moving: 'التحرك',
|
||||
movingCount: 'نقل {{count}} {{label}}',
|
||||
newLabel: 'جديد {{label}}',
|
||||
newPassword: 'كلمة مرور جديدة',
|
||||
next: 'التالي',
|
||||
no: 'لا',
|
||||
|
||||
@@ -288,7 +288,6 @@ export const azTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Silinib Tarixi',
|
||||
deletedCountSuccessfully: '{{count}} {{label}} uğurla silindi.',
|
||||
deletedSuccessfully: 'Uğurla silindi.',
|
||||
deleteLabel: '{{label}} silin',
|
||||
deletePermanently: 'Çöplüyü atlayın və daimi olaraq silin',
|
||||
deleting: 'Silinir...',
|
||||
depth: 'Dərinlik',
|
||||
@@ -349,7 +348,6 @@ export const azTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Yuxarı hərəkət et',
|
||||
moving: 'Hərəkət edir',
|
||||
movingCount: '{{count}} {{label}} köçürülür',
|
||||
newLabel: 'Yeni {{label}}',
|
||||
newPassword: 'Yeni şifrə',
|
||||
next: 'Növbəti',
|
||||
no: 'Xeyr',
|
||||
|
||||
@@ -285,7 +285,6 @@ export const bgTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Изтрито на',
|
||||
deletedCountSuccessfully: 'Изтрити {{count}} {{label}} успешно.',
|
||||
deletedSuccessfully: 'Изтрито успешно.',
|
||||
deleteLabel: 'Изтрий {{label}}',
|
||||
deletePermanently: 'Пропуснете кошчето и изтрийте перманентно',
|
||||
deleting: 'Изтриване...',
|
||||
depth: 'Дълбочина',
|
||||
@@ -346,7 +345,6 @@ export const bgTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Нагоре',
|
||||
moving: 'Преместване',
|
||||
movingCount: 'Преместване на {{count}} {{label}}',
|
||||
newLabel: 'Нов {{label}}',
|
||||
newPassword: 'Нова парола',
|
||||
next: 'Следващ',
|
||||
no: 'Не',
|
||||
|
||||
@@ -290,7 +290,6 @@ export const bnBdTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'মুছে ফেলার সময়',
|
||||
deletedCountSuccessfully: '{{count}} {{label}} সফলভাবে মুছে ফেলা হয়েছে।',
|
||||
deletedSuccessfully: 'সফলভাবে মুছে ফেলা হয়েছে।',
|
||||
deleteLabel: '{{label}} মুছে ফেলুন',
|
||||
deletePermanently: 'ট্র্যাশ এড়িয়ে স্থায়ীভাবে মুছুন',
|
||||
deleting: 'মুছে ফেলা হচ্ছে...',
|
||||
depth: 'গভীরতা',
|
||||
@@ -351,7 +350,6 @@ export const bnBdTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'উপরে সরান',
|
||||
moving: 'স্থানান্তর করা হচ্ছে',
|
||||
movingCount: '{{count}} {{label}} স্থানান্তর করা হচ্ছে',
|
||||
newLabel: 'নতুন {{label}}',
|
||||
newPassword: 'নতুন পাসওয়ার্ড',
|
||||
next: 'পরবর্তী',
|
||||
no: 'না',
|
||||
|
||||
@@ -289,7 +289,6 @@ export const bnInTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'মুছে ফেলার সময়',
|
||||
deletedCountSuccessfully: '{{count}} {{label}} সফলভাবে মুছে ফেলা হয়েছে।',
|
||||
deletedSuccessfully: 'সফলভাবে মুছে ফেলা হয়েছে।',
|
||||
deleteLabel: '{{label}} মুছে ফেলুন',
|
||||
deletePermanently: 'ট্র্যাশ এড়িয়ে চিরতরে মুছে ফেলুন',
|
||||
deleting: 'মুছে ফেলা হচ্ছে...',
|
||||
depth: 'গভীরতা',
|
||||
@@ -350,7 +349,6 @@ export const bnInTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'উপরে সরান',
|
||||
moving: 'স্থানান্তর করা হচ্ছে',
|
||||
movingCount: '{{count}} {{label}} স্থানান্তর করা হচ্ছে',
|
||||
newLabel: 'নতুন {{label}}',
|
||||
newPassword: 'নতুন পাসওয়ার্ড',
|
||||
next: 'পরবর্তী',
|
||||
no: 'না',
|
||||
|
||||
@@ -287,7 +287,6 @@ export const caTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Eliminat en',
|
||||
deletedCountSuccessfully: 'Eliminat {{count}} {{label}} correctament.',
|
||||
deletedSuccessfully: 'Eliminat correntament.',
|
||||
deleteLabel: 'Esborra {{label}}',
|
||||
deletePermanently: 'Omet la paperera i elimina permanentment',
|
||||
deleting: 'Eliminant...',
|
||||
depth: 'Profunditat',
|
||||
@@ -348,7 +347,6 @@ export const caTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Move amunt',
|
||||
moving: 'En moviment',
|
||||
movingCount: 'Moure {{count}} {{label}}',
|
||||
newLabel: 'Nou {{label}}',
|
||||
newPassword: 'Nova contrasenya',
|
||||
next: 'Seguent',
|
||||
no: 'No',
|
||||
|
||||
@@ -284,7 +284,6 @@ export const csTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Smazáno dne',
|
||||
deletedCountSuccessfully: 'Úspěšně smazáno {{count}} {{label}}.',
|
||||
deletedSuccessfully: 'Úspěšně odstraněno.',
|
||||
deleteLabel: 'Smazat {{label}}',
|
||||
deletePermanently: 'Preskočit koš a smazat trvale',
|
||||
deleting: 'Odstraňování...',
|
||||
depth: 'Hloubka',
|
||||
@@ -345,7 +344,6 @@ export const csTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Posunout nahoru',
|
||||
moving: 'Přesun',
|
||||
movingCount: 'Přesunout {{count}} {{label}}',
|
||||
newLabel: 'Nový {{label}}',
|
||||
newPassword: 'Nové heslo',
|
||||
next: 'Další',
|
||||
no: 'Ne',
|
||||
|
||||
@@ -284,7 +284,6 @@ export const daTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Slettet Ved',
|
||||
deletedCountSuccessfully: 'Slettet {{count}} {{label}}.',
|
||||
deletedSuccessfully: 'Slettet.',
|
||||
deleteLabel: 'Slet {{label}}',
|
||||
deletePermanently: 'Spring affald over og slet permanent',
|
||||
deleting: 'Sletter...',
|
||||
depth: 'Dybde',
|
||||
@@ -345,7 +344,6 @@ export const daTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Ryk op',
|
||||
moving: 'Flytter',
|
||||
movingCount: 'Flytter {{count}} {{label}}',
|
||||
newLabel: 'Ny {{label}}',
|
||||
newPassword: 'Ny adgangskode',
|
||||
next: 'Næste',
|
||||
no: 'Nej',
|
||||
|
||||
@@ -295,7 +295,6 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Gelöscht am',
|
||||
deletedCountSuccessfully: '{{count}} {{label}} erfolgreich gelöscht.',
|
||||
deletedSuccessfully: 'Erfolgreich gelöscht.',
|
||||
deleteLabel: '{{label}} löschen',
|
||||
deletePermanently: 'Überspringen Sie den Papierkorb und löschen Sie dauerhaft.',
|
||||
deleting: 'Löschen...',
|
||||
depth: 'Tiefe',
|
||||
@@ -356,7 +355,6 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Nach oben bewegen',
|
||||
moving: 'Umziehen',
|
||||
movingCount: 'Verschieben {{count}} {{label}}',
|
||||
newLabel: 'Neu {{label}}',
|
||||
newPassword: 'Neues Passwort',
|
||||
next: 'Nächste',
|
||||
no: 'Nein',
|
||||
|
||||
@@ -289,7 +289,6 @@ export const enTranslations = {
|
||||
deletedAt: 'Deleted At',
|
||||
deletedCountSuccessfully: 'Deleted {{count}} {{label}} successfully.',
|
||||
deletedSuccessfully: 'Deleted successfully.',
|
||||
deleteLabel: 'Delete {{label}}',
|
||||
deletePermanently: 'Skip trash and delete permanently',
|
||||
deleting: 'Deleting...',
|
||||
depth: 'Depth',
|
||||
@@ -350,7 +349,6 @@ export const enTranslations = {
|
||||
moveUp: 'Move Up',
|
||||
moving: 'Moving',
|
||||
movingCount: 'Moving {{count}} {{label}}',
|
||||
newLabel: 'New {{label}}',
|
||||
newPassword: 'New Password',
|
||||
next: 'Next',
|
||||
no: 'No',
|
||||
|
||||
@@ -291,7 +291,6 @@ export const esTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Eliminado En',
|
||||
deletedCountSuccessfully: 'Se eliminaron {{count}} {{label}} correctamente.',
|
||||
deletedSuccessfully: 'Eliminado correctamente.',
|
||||
deleteLabel: 'Eliminar {{label}}',
|
||||
deletePermanently: 'Omitir la papelera y eliminar permanentemente',
|
||||
deleting: 'Eliminando...',
|
||||
depth: 'Profundidad',
|
||||
@@ -352,7 +351,6 @@ export const esTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Mover arriba',
|
||||
moving: 'Moviendo',
|
||||
movingCount: 'Moviendo {{count}} {{label}}',
|
||||
newLabel: 'Nuevo {{label}}',
|
||||
newPassword: 'Nueva contraseña',
|
||||
next: 'Siguiente',
|
||||
no: 'No',
|
||||
|
||||
@@ -283,7 +283,6 @@ export const etTranslations: DefaultTranslationsObject = {
|
||||
deletedAt: 'Kustutatud',
|
||||
deletedCountSuccessfully: 'Kustutatud {{count}} {{label}} edukalt.',
|
||||
deletedSuccessfully: 'Kustutatud edukalt.',
|
||||
deleteLabel: 'Kustuta {{label}}',
|
||||
deletePermanently: 'Jäta prügikasti vahele ja kustuta lõplikult',
|
||||
deleting: 'Kustutamine...',
|
||||
depth: 'Sügavus',
|
||||
@@ -343,7 +342,6 @@ export const etTranslations: DefaultTranslationsObject = {
|
||||
moveUp: 'Liiguta üles',
|
||||
moving: 'Liikumine',
|
||||
movingCount: 'Liigutan {{count}} {{label}}',
|
||||
newLabel: 'Uus {{label}}',
|
||||
newPassword: 'Uus parool',
|
||||
next: 'Järgmine',
|
||||
no: 'Ei',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user