Compare commits

..

1 Commits

Author SHA1 Message Date
Elliot DeNolf
798515a0a8 chore(release): richtext-lexical/0.1.7 2023-10-13 12:48:19 -04:00
189 changed files with 3879 additions and 8184 deletions

View File

@@ -213,9 +213,8 @@ jobs:
fail-fast: false
matrix:
pkg:
- create-payload-app
- plugin-cloud
- plugin-nested-docs
- create-payload-app
steps:
- name: Use Node.js 18

View File

@@ -1,86 +1,3 @@
## [2.0.6](https://github.com/payloadcms/payload/compare/v2.0.5...v2.0.6) (2023-10-14)
### Bug Fixes
* document sidebar vertical overflow ([#3639](https://github.com/payloadcms/payload/issues/3639)) ([fcd4c8d](https://github.com/payloadcms/payload/commit/fcd4c8d83040f00d10142ca12ba92616618b966e))
* login form clearing out and field spacing ([#3633](https://github.com/payloadcms/payload/issues/3633)) ([4bd01df](https://github.com/payloadcms/payload/commit/4bd01df411e4ad2ccacdcd6de0fb21a8145c3964))
* sidebar field permissions ([#3629](https://github.com/payloadcms/payload/issues/3629)) ([c956a85](https://github.com/payloadcms/payload/commit/c956a85252bc7de1686925cc783694383c0ac9be))
* preview button conditions ([#3613](https://github.com/payloadcms/payload/issues/3613)) ([beed83b](https://github.com/payloadcms/payload/commit/beed83b231b19090902dd502ff5eab054a67a1a6))
* allows drafts to be duplicated ([1a99d66](https://github.com/payloadcms/payload/commit/1a99d66cd0675cf2cb2c4317a121721f35682ff3))
## [2.0.5](https://github.com/payloadcms/payload/compare/v2.0.4...v2.0.5) (2023-10-12)
### Bug Fixes
* properly renders custom buttons for globals ([#3616](https://github.com/payloadcms/payload/issues/3616)) ([05cc287](https://github.com/payloadcms/payload/commit/05cc2873b4a19e2bd46be778f3610643d3e15d09))
* minor type issue in richText validate function ([06a51b3](https://github.com/payloadcms/payload/commit/06a51b3c9b9045b23051807aa03b222b542b46f5))
* live preview device size ([#3606](https://github.com/payloadcms/payload/issues/3606)) ([8bbac60](https://github.com/payloadcms/payload/commit/8bbac60e60a6dbe4dc0c7b05edbca7f6f2d1c569))
* properly handles nested routes for live preview ([#3586](https://github.com/payloadcms/payload/issues/3586)) ([6486468](https://github.com/payloadcms/payload/commit/64864686c418f9822bf61c45ece078a39e81b4cb))
* various stepnav related issues ([#3599](https://github.com/payloadcms/payload/issues/3599)) ([aaf8839](https://github.com/payloadcms/payload/commit/aaf883909c588bae1145ddddc5291a98740c2c03))
* database adapter types ([cc56da1](https://github.com/payloadcms/payload/commit/cc56da11d635d11ebbee67e6d0919c7275ede36e))
* postgres select fields within groups ([#3570](https://github.com/payloadcms/payload/issues/3570)) ([06e2fa9](https://github.com/payloadcms/payload/commit/06e2fa9d111c18fad3422953082266db9329fc91))
* [#3511](https://github.com/payloadcms/payload/issues/3511), documents don't delete their versions ([#3520](https://github.com/payloadcms/payload/issues/3520)) ([e3c7765](https://github.com/payloadcms/payload/commit/e3c776523a64da03a4756ee5ae8a84175090979f))
### Documentation
- updates building your own live preview hook ([#3604](https://github.com/payloadcms/payload/issues/3604)) ([15c7f0dbf](https://github.com/payloadcms/payload/commit/15c7f0dbf3ebf5c6a2bb011970dda515a15acb56))
- update config overview ([cfd923140](https://github.com/payloadcms/payload/commit/1a006fef19a215d7ef74c71a210fd511727f95bd))
## [2.0.4](https://github.com/payloadcms/payload/compare/v2.0.3...v2.0.4) (2023-10-12)
### Bug Fixes
- API tab breadcrumbs and results indentation ([#3564](https://github.com/payloadcms/payload/issues/3564)) ([e0afeec](https://github.com/payloadcms/payload/commit/e0afeeca974d0a0cac7aca8e40f9436449c902b5))
- sticky sidebar ([#3563](https://github.com/payloadcms/payload/issues/3563)) ([76e306d](https://github.com/payloadcms/payload/commit/76e306ddd8aae45f03fd4715415d6a44501a9400))
- sidebar width when fields have long descriptions ([#3562](https://github.com/payloadcms/payload/issues/3562)) ([cfc78ed](https://github.com/payloadcms/payload/commit/cfc78ed4f58647769f651da5a952fed20cfb217f))
- row field margins ([#3558](https://github.com/payloadcms/payload/issues/3558)) ([6d9353b](https://github.com/payloadcms/payload/commit/6d9353b53f4197bae2b15ca95298a87d784c7e76))
- removes nested array field configs from array value ([#3549](https://github.com/payloadcms/payload/issues/3549)) ([af892ec](https://github.com/payloadcms/payload/commit/af892ecb0e67777a97206bb5fccf489387ce68fc))
- [#3521](https://github.com/payloadcms/payload/issues/3521) ([eb97acd](https://github.com/payloadcms/payload/commit/eb97acd408f128438c2122ab6a6e2930f5b4a1ca))
- [#3540](https://github.com/payloadcms/payload/issues/3540) ([2567ac5](https://github.com/payloadcms/payload/commit/2567ac58bac851d0a15ee40db0f5f4737b199a75))
- row field width ([#3550](https://github.com/payloadcms/payload/issues/3550)) ([9ff014b](https://github.com/payloadcms/payload/commit/9ff014bbfe08d7b114c11824294f0d59f5f6c2c3))
- [#3541](https://github.com/payloadcms/payload/issues/3541) ([e6f0d35](https://github.com/payloadcms/payload/commit/e6f0d3598549a921e36f470adfcbacbaebaea53f))
- renders global label as page title ([#3532](https://github.com/payloadcms/payload/issues/3532)) ([ace3e57](https://github.com/payloadcms/payload/commit/ace3e577f6b1cbeb12860dc936c578c2a1f68570))
- increases document controls popup list button hitbox ([#3529](https://github.com/payloadcms/payload/issues/3529)) ([f009593](https://github.com/payloadcms/payload/commit/f0095937bafdd85c53c99bcc1d29d3361aa07238))
### Documentation
- removes MONGODB_URI ([8bfae6b93](https://github.com/payloadcms/payload/commit/8bfae6b932d6c9bd0c628a203ebf8d24121d66f8))
- adds build your own plugin page ([#3184](https://github.com/payloadcms/payload/pull/3184)) ([15f650afd](https://github.com/payloadcms/payload/commit/15f650afdef717d62c162846fec77aa0f326bb43))
## [2.0.3](https://github.com/payloadcms/payload/compare/v2.0.2...v2.0.3) (2023-10-09)
### Bug Fixes
- webpack export default was not found [#3494](https://github.com/payloadcms/payload/issues/3494) ([be049ce](https://github.com/payloadcms/payload/commit/be049cea0029cf497822e337777b8a86b7d38bed))
- postgres generated type id [#3504](https://github.com/payloadcms/payload/issues/3504) ([c90d1fa](https://github.com/payloadcms/payload/commit/c90d1faa7fedd5d902949089fd457c56eed4643d))
- hasMany relationships unable to be cleared [#3513](https://github.com/payloadcms/payload/issues/3513) ([5d9384f](https://github.com/payloadcms/payload/commit/5d9384f53052c96403d8c07ae9d05edf3676c4ef))
### Documentation
- move payload script mention to top of migrations ([26967fb92](https://github.com/payloadcms/payload/commit/26967fb92))
- payload script in package.json ([2f86c196e](https://github.com/payloadcms/payload/commit/2f86c196e))
- updates required node version ([70e068b18](https://github.com/payloadcms/payload/commit/70e068b18))
- improves custom views (#3499) ([6c17222a6](https://github.com/payloadcms/payload/commit/6c17222a6))
## [2.0.2](https://github.com/payloadcms/payload/compare/v2.0.1...v2.0.2) (2023-10-09)
### Bug Fixes
- beforeOperation hooks now correctly only run once ([e5d6a75](https://github.com/payloadcms/payload/commit/e5d6a75449acce2e53820a65386f1af78ff1317b))
## [2.0.1](https://github.com/payloadcms/payload/compare/v2.0.0...v2.0.1) (2023-10-09)
### Bug Fixes
- fix: richtext adapter types (#3497) ([7679e3f0a](https://github.com/payloadcms/payload/commit/7679e3f0aa351832ca933a3978d5931c47375e8b))
### Documentation
- remove --save flag for install command ([f7c35df6d](https://github.com/payloadcms/payload/commit/f7c35df6de6817ef33837f60951cd2812431fec7))
- updates live preview docs ([ca97f692c](https://github.com/payloadcms/payload/commit/ca97f692c3d470e658e417daf29213b2b2b49e11))
- fixes label for rich text overview ([7df1256bf](https://github.com/payloadcms/payload/commit/7df1256bf61daa911089d308cf7c0532d524c9c6))
## [2.0.0](https://github.com/payloadcms/payload/releases/tag/v2.0.0) (2023-10-09)
### Features
@@ -206,7 +123,7 @@ To avoid any issues, you can pass the `req.transactionID` through to your Local
### ⚠️ Locales now have more functionality, and in some places, you might need to update custom code
Payload's locales have become more powerful and now allow you to customize more aspects per locale such as a human-friendly label and if the locale is RTL or not.
Payload's locales have become more powerful and now allow you to customize more aspects per locale such as a human-friendly label and if the locale is RTL or not.
This means that certain functions now return a different shape, such as `useLocale`. This hook used to return a string of the locale code you are currently editing, but it now returns an object with type of `Locale`.
@@ -301,7 +218,7 @@ To pass connection options for MongoDB, you now need to pass them to `db: mongoo
### ⚠️ Some types have changed locations
If you are importing types from Payload, some of their locations may have changed. An example would be Slate-specific types being no longer exported from Payload itself—they are now exported from the `@payloadcms/richtext-slate` package.
If you are importing types from Payload, some of their locations may have changed. An example would be Slate-specific types being no longer exported from Payload itself—they are now exported from the `@payloadcms/richtext-slate` package.
### Recap

View File

@@ -129,7 +129,7 @@ To add a _new_ view to the Admin Panel, simply add another key to the `views` ob
}
```
_For more examples regarding how to customize components, look at the following [examples](https://github.com/payloadcms/payload/tree/main/test/admin/components)._
_For more examples regarding how to customize components, look at the following [examples](https://github.com/payloadcms/payload/tree/master/test/admin/components)._
For help on how to build your own custom view components, see [building a custom view component](#building-a-custom-view-component).
@@ -399,12 +399,12 @@ Your custom view components will be given all the props that a React Router `<Ro
#### Example
You can find examples of custom views in the [Payload source code `/test/admin/components/views` folder](https://github.com/payloadcms/payload/tree/main/test/admin/components/views). There, you'll find two custom views:
You can find examples of custom views in the [Payload source code `/test/admin/components/views` folder](https://github.com/payloadcms/payload/tree/master/test/admin/components/views). There, you'll find two custom views:
1. A custom view that uses the `DefaultTemplate`, which is the built-in Payload template that displays the sidebar and "eyebrow nav"
1. A custom view that uses the `MinimalTemplate` - which is just a centered template used for things like logging in or out
To see how to pass in your custom views to create custom views of your own, take a look at the `admin.components.views` property of the [Payload test admin config](https://github.com/payloadcms/payload/blob/main/test/admin/config.ts).
To see how to pass in your custom views to create custom views of your own, take a look at the `admin.components.views` property of the [Payload test admin config](https://github.com/payloadcms/payload/blob/master/test/admin/config.ts).
### Fields

View File

@@ -131,7 +131,6 @@ const result = await payload.find({
depth: 2,
page: 1,
limit: 10,
pagination: false, // If you want to disable pagination count, etc.
where: {}, // pass a `where` query here
sort: '-title',
locale: 'en',

View File

@@ -59,7 +59,3 @@ All Payload APIs support the pagination controls below. With them, you can creat
| ------- | --------------------------------------- |
| `limit` | Limits the number of documents returned |
| `page` | Get a specific page number |
### Disabling pagination within Local API
For `find` operations within the Local API, you can disable pagination to retrieve all documents from a collection by passing `pagination: false` to the `find` local operation. This is not supported in REST or GraphQL, however, because it could potentially lead to malicious activity.

View File

@@ -17,9 +17,9 @@
"lint:fix": "eslint --fix --ext .ts,.tsx src"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"

File diff suppressed because it is too large Load Diff

View File

@@ -20,9 +20,9 @@
"lint:fix": "eslint --fix --ext .ts,.tsx src"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"dotenv": "^8.2.0",
"escape-html": "^1.0.3",
"express": "^4.17.1",

File diff suppressed because it is too large Load Diff

View File

@@ -18,9 +18,9 @@
"lint:fix": "eslint --fix --ext .ts,.tsx src"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"

File diff suppressed because it is too large Load Diff

View File

@@ -15,9 +15,9 @@
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"@faceless-ui/modal": "^2.0.1",
"@payloadcms/plugin-form-builder": "^1.0.12",
"@payloadcms/plugin-seo": "^1.0.8",

File diff suppressed because it is too large Load Diff

View File

@@ -18,9 +18,9 @@
"lint:fix": "eslint --fix --ext .ts,.tsx src"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"

File diff suppressed because it is too large Load Diff

View File

@@ -18,9 +18,9 @@
"lint:fix": "eslint --fix --ext .ts,.tsx src"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"

File diff suppressed because it is too large Load Diff

View File

@@ -17,9 +17,9 @@
"lint:fix": "eslint --fix --ext .ts,.tsx src"
},
"dependencies": {
"@payloadcms/bundler-webpack": "latest",
"@payloadcms/db-mongodb": "latest",
"@payloadcms/richtext-slate": "latest",
"@payloadcms/bundler-webpack": "^1.0.0-beta.5",
"@payloadcms/db-mongodb": "^1.0.0-beta.8",
"@payloadcms/richtext-slate": "^1.0.0-beta.4",
"@payloadcms/plugin-redirects": "^1.0.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",

File diff suppressed because it is too large Load Diff

View File

@@ -496,16 +496,6 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
"@babel/generator@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
dependencies:
"@babel/types" "^7.23.0"
"@jridgewell/gen-mapping" "^0.3.2"
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
"@babel/helper-compilation-targets@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52"
@@ -517,23 +507,18 @@
lru-cache "^5.1.1"
semver "^6.3.1"
"@babel/helper-environment-visitor@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
"@babel/helper-environment-visitor@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
"@babel/helper-function-name@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
"@babel/helper-function-name@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
dependencies:
"@babel/template" "^7.22.15"
"@babel/types" "^7.23.0"
"@babel/template" "^7.22.5"
"@babel/types" "^7.22.5"
"@babel/helper-hoist-variables@^7.22.5":
version "7.22.5"
@@ -589,11 +574,6 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044"
integrity sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==
"@babel/helper-validator-identifier@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
"@babel/helper-validator-option@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
@@ -622,11 +602,6 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95"
integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==
"@babel/parser@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
"@babel/plugin-syntax-async-generators@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
@@ -732,7 +707,7 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.3.3":
"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
@@ -742,18 +717,18 @@
"@babel/types" "^7.22.15"
"@babel/traverse@^7.22.15", "@babel/traverse@^7.22.17":
version "7.23.2"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
version "7.22.17"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.17.tgz#b23c203ab3707e3be816043081b4a994fcacec44"
integrity sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==
dependencies:
"@babel/code-frame" "^7.22.13"
"@babel/generator" "^7.23.0"
"@babel/helper-environment-visitor" "^7.22.20"
"@babel/helper-function-name" "^7.23.0"
"@babel/generator" "^7.22.15"
"@babel/helper-environment-visitor" "^7.22.5"
"@babel/helper-function-name" "^7.22.5"
"@babel/helper-hoist-variables" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/parser" "^7.23.0"
"@babel/types" "^7.23.0"
"@babel/parser" "^7.22.16"
"@babel/types" "^7.22.17"
debug "^4.1.0"
globals "^11.1.0"
@@ -766,15 +741,6 @@
"@babel/helper-validator-identifier" "^7.22.15"
to-fast-properties "^2.0.0"
"@babel/types@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
dependencies:
"@babel/helper-string-parser" "^7.22.5"
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
"@bcherny/json-schema-ref-parser@9.0.9":
version "9.0.9"
resolved "https://registry.yarnpkg.com/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#09899d405bc708c0acac0066ae8db5b94d465ca4"

View File

@@ -20,8 +20,8 @@
"lint-staged": "lint-staged",
"pretest": "pnpm build",
"reinstall": "pnpm clean:unix && pnpm install",
"script:list-packages": "tsx ./scripts/list-packages.ts",
"script:release": "tsx ./scripts/release.ts",
"list:packages": "./scripts/list_published_packages.sh beta",
"script:release:beta": "./scripts/release_beta.sh",
"test": "pnpm test:int && pnpm test:components && pnpm test:e2e",
"test:components": "cross-env jest --config=jest.components.config.js",
"test:e2e": "npx playwright install --with-deps && ts-node -T ./test/runE2E.ts",
@@ -47,7 +47,6 @@
"@types/prompts": "^2.4.5",
"@types/qs": "6.9.7",
"@types/react": "18.2.15",
"@types/semver": "^7.5.3",
"@types/shelljs": "0.8.12",
"@types/testing-library__jest-dom": "5.14.8",
"chalk": "^5.3.0",
@@ -60,7 +59,6 @@
"fs-extra": "10.1.0",
"get-port": "5.1.1",
"glob": "8.1.0",
"graphql-request": "6.1.0",
"husky": "^8.0.3",
"isomorphic-fetch": "3.0.0",
"jest": "29.6.4",
@@ -75,7 +73,6 @@
"prompts": "2.4.2",
"qs": "6.11.2",
"rimraf": "3.0.2",
"semver": "^7.5.4",
"shelljs": "0.8.5",
"simple-git": "^3.20.0",
"slash": "3.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@payloadcms/db-postgres",
"version": "0.1.8",
"version": "0.1.4",
"description": "The officially supported Postgres database adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",
@@ -34,6 +34,9 @@
"@types/to-snake-case": "1.0.0",
"payload": "workspace:*"
},
"peerDependencies": {
"better-sqlite3": "^8.5.0"
},
"publishConfig": {
"main": "./dist/index.js",
"registry": "https://registry.npmjs.org/",

View File

@@ -1,5 +1,6 @@
import type { Connect } from 'payload/database'
import { pushSchema } from 'drizzle-kit/utils'
import { eq, sql } from 'drizzle-orm'
import { drizzle } from 'drizzle-orm/node-postgres'
import { numeric, pgTable, timestamp, varchar } from 'drizzle-orm/pg-core'
@@ -39,8 +40,6 @@ export const connect: Connect = async function connect(this: PostgresAdapter, pa
)
return
const { pushSchema } = require('drizzle-kit/utils')
// This will prompt if clarifications are needed for Drizzle to push new schema
const { apply, hasDataLoss, statementsToExecute, warnings } = await pushSchema(
this.schema,

View File

@@ -2,6 +2,7 @@
import type { DrizzleSnapshotJSON } from 'drizzle-kit/utils'
import type { CreateMigration } from 'payload/database'
import { generateDrizzleJson, generateMigration } from 'drizzle-kit/utils'
import fs from 'fs'
import prompts from 'prompts'
@@ -60,8 +61,6 @@ export const createMigration: CreateMigration = async function createMigration(
fs.mkdirSync(dir)
}
const { generateDrizzleJson, generateMigration } = require('drizzle-kit/utils')
const [yyymmdd, hhmmss] = new Date().toISOString().split('T')
const formattedDate = yyymmdd.replace(/\D/g, '')
const formattedTime = hhmmss.split('.')[0].replace(/\D/g, '')

View File

@@ -33,7 +33,7 @@ export const findMany = async function find({
const db = adapter.sessions[req.transactionID]?.db || adapter.drizzle
const table = adapter.tables[tableName]
let limit = limitArg ?? 10
let limit = limitArg
let totalDocs: number
let totalPages: number
let hasPrevPage: boolean
@@ -119,11 +119,7 @@ export const findMany = async function find({
findManyArgs.where = inArray(adapter.tables[tableName].id, Object.keys(orderedIDMap))
} else {
findManyArgs.limit = limitArg === 0 ? undefined : limitArg
const offset = skip || (page - 1) * limitArg
if (!Number.isNaN(offset)) findManyArgs.offset = offset
findManyArgs.offset = skip || (page - 1) * limitArg
if (where) {
findManyArgs.where = where
}

View File

@@ -2,7 +2,9 @@
import type { Payload } from 'payload'
import type { Migration } from 'payload/database'
import { generateDrizzleJson } from 'drizzle-kit/utils'
import { readMigrationFiles } from 'payload/database'
import { DatabaseError } from 'pg'
import prompts from 'prompts'
import type { PostgresAdapter } from './types'
@@ -76,8 +78,6 @@ export async function migrate(this: PostgresAdapter): Promise<void> {
}
async function runMigrationFile(payload: Payload, migration: Migration, batch: number) {
const { generateDrizzleJson } = require('drizzle-kit/utils')
const start = Date.now()
payload.logger.info({ msg: `Migrating: ${migration.name}` })

View File

@@ -34,14 +34,12 @@ type Args = {
aliasTable?: GenericTable
collectionPath: string
columnPrefix?: string
constraintPath?: string
constraints?: Constraint[]
fields: (Field | TabAsField)[]
joinAliases: BuildQueryJoinAliases
joins: BuildQueryJoins
locale?: string
pathSegments: string[]
rootTableName?: string
selectFields: Record<string, GenericColumn>
tableName: string
}
@@ -55,22 +53,17 @@ export const getTableColumnFromPath = ({
aliasTable,
collectionPath,
columnPrefix = '',
constraintPath: incomingConstraintPath,
constraints = [],
fields,
joinAliases,
joins,
locale: incomingLocale,
pathSegments: incomingSegments,
rootTableName: incomingRootTableName,
selectFields,
tableName,
}: Args): TableColumn => {
const fieldPath = incomingSegments[0]
let locale = incomingLocale
const rootTableName = incomingRootTableName || tableName
let constraintPath = incomingConstraintPath || ''
const field = flattenTopLevelFields(fields as Field[]).find(
(fieldToFind) => fieldAffectsData(fieldToFind) && fieldToFind.name === fieldPath,
) as Field | TabAsField
@@ -112,7 +105,6 @@ export const getTableColumnFromPath = ({
aliasTable,
collectionPath,
columnPrefix,
constraintPath,
constraints,
fields: field.tabs.map((tab) => ({
...tab,
@@ -122,7 +114,6 @@ export const getTableColumnFromPath = ({
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName,
selectFields,
tableName: newTableName,
})
@@ -134,14 +125,12 @@ export const getTableColumnFromPath = ({
aliasTable,
collectionPath,
columnPrefix: `${columnPrefix}${field.name}_`,
constraintPath,
constraints,
fields: field.fields,
joinAliases,
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName,
selectFields,
tableName: newTableName,
})
@@ -151,14 +140,12 @@ export const getTableColumnFromPath = ({
aliasTable,
collectionPath,
columnPrefix,
constraintPath,
constraints,
fields: field.fields,
joinAliases,
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName,
selectFields,
tableName: newTableName,
})
@@ -185,14 +172,12 @@ export const getTableColumnFromPath = ({
aliasTable,
collectionPath,
columnPrefix: `${columnPrefix}${field.name}_`,
constraintPath,
constraints,
fields: field.fields,
joinAliases,
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName,
selectFields,
tableName: newTableName,
})
@@ -200,7 +185,6 @@ export const getTableColumnFromPath = ({
case 'array': {
newTableName = `${tableName}_${toSnakeCase(field.name)}`
constraintPath = `${constraintPath}${field.name}.%.`
if (locale && field.localized && adapter.payload.config.localization) {
joins[newTableName] = and(
eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID),
@@ -222,14 +206,12 @@ export const getTableColumnFromPath = ({
return getTableColumnFromPath({
adapter,
collectionPath,
constraintPath,
constraints,
fields: field.fields,
joinAliases,
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName,
selectFields,
tableName: newTableName,
})
@@ -247,14 +229,12 @@ export const getTableColumnFromPath = ({
result = getTableColumnFromPath({
adapter,
collectionPath,
constraintPath: '',
constraints: blockConstraints,
fields: block.fields,
joinAliases,
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName,
selectFields: blockSelectFields,
tableName: newTableName,
})
@@ -303,8 +283,9 @@ export const getTableColumnFromPath = ({
case 'relationship':
case 'upload': {
let relationshipFields
const relationTableName = `${rootTableName}_rels`
const relationTableName = `${tableName}_rels`
const newCollectionPath = pathSegments.slice(1).join('.')
const aliasRelationshipTableName = uuid()
const aliasRelationshipTable = alias(
adapter.tables[relationTableName],
@@ -314,7 +295,7 @@ export const getTableColumnFromPath = ({
// Join in the relationships table
joinAliases.push({
condition: eq(
(aliasTable || adapter.tables[rootTableName]).id,
(aliasTable || adapter.tables[tableName]).id,
aliasRelationshipTable.parent,
),
table: aliasRelationshipTable,
@@ -325,7 +306,7 @@ export const getTableColumnFromPath = ({
constraints.push({
columnName: 'path',
table: aliasRelationshipTable,
value: `${constraintPath}${field.name}`,
value: field.name,
})
let newAliasTable
@@ -387,7 +368,6 @@ export const getTableColumnFromPath = ({
joins,
locale,
pathSegments: pathSegments.slice(1),
rootTableName: newTableName,
selectFields,
tableName: newTableName,
})

View File

@@ -100,11 +100,7 @@ export async function parseParams({
const val = where[relationOrPath][operator]
queryConstraints.forEach(({ columnName: col, table: constraintTable, value }) => {
if (typeof value === 'string' && value.indexOf('%') > -1) {
constraints.push(operatorMap.like(constraintTable[col], value))
} else {
constraints.push(operatorMap.equals(constraintTable[col], value))
}
constraints.push(operatorMap.equals(constraintTable[col], value))
})
if (['json', 'richText'].includes(field.type) && Array.isArray(pathSegments)) {
@@ -148,19 +144,13 @@ export async function parseParams({
break
}
const sanitizedQueryValue = sanitizeQueryValue({
const { operator: queryOperator, value: queryValue } = sanitizeQueryValue({
field,
operator,
relationOrPath,
val,
})
if (sanitizedQueryValue === null) {
break
}
const { operator: queryOperator, value: queryValue } = sanitizedQueryValue
if (queryOperator === 'not_equals' && queryValue !== null) {
constraints.push(
or(
@@ -169,10 +159,7 @@ export async function parseParams({
ne<any>(rawColumn || table[columnName], queryValue),
),
)
break
}
if (
} else if (
(field.type === 'relationship' || field.type === 'upload') &&
Array.isArray(queryValue) &&
operator === 'not_in'
@@ -183,13 +170,11 @@ export async function parseParams({
IS
NULL`,
)
break
} else {
constraints.push(
operatorMap[queryOperator](rawColumn || table[columnName], queryValue),
)
}
constraints.push(
operatorMap[queryOperator](rawColumn || table[columnName], queryValue),
)
}
}
}

View File

@@ -42,17 +42,11 @@ export const sanitizeQueryValue = ({
if (val.toLowerCase() === 'false') formattedValue = false
}
if (['all', 'in', 'not_in'].includes(operator)) {
if (typeof formattedValue === 'string') {
formattedValue = createArrayFromCommaDelineated(formattedValue)
if (['all', 'in', 'not_in'].includes(operator) && typeof formattedValue === 'string') {
formattedValue = createArrayFromCommaDelineated(formattedValue)
if (field.type === 'number') {
formattedValue = formattedValue.map((arrayVal) => parseFloat(arrayVal))
}
}
if (!Array.isArray(formattedValue) || formattedValue.length === 0) {
return null
if (field.type === 'number') {
formattedValue = formattedValue.map((arrayVal) => parseFloat(arrayVal))
}
}

View File

@@ -6,12 +6,11 @@
// drizzle-kit@utils
import { generateDrizzleJson, generateMigration, pushSchema } from 'drizzle-kit/utils'
import { drizzle } from 'drizzle-orm/node-postgres'
import { Pool } from 'pg'
async function generateUsage() {
const { generateDrizzleJson, generateMigration } = require('drizzle-kit/utils')
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
const schema = await import('./data/users')
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
@@ -26,8 +25,6 @@ async function generateUsage() {
}
async function pushUsage() {
const { pushSchema } = require('drizzle-kit/utils')
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
const schemaAfter = await import('./data/users-after')

View File

@@ -252,8 +252,6 @@ export const traverseFields = ({
}
case 'array': {
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
const arrayTableName = `${newTableName}_${toSnakeCase(field.name)}`
const baseColumns: Record<string, PgColumnBuilder> = {
_order: integer('_order').notNull(),
@@ -279,7 +277,7 @@ export const traverseFields = ({
adapter,
baseColumns,
baseExtraConfig,
disableNotNull: disableNotNullFromHere,
disableNotNull,
disableUnique,
fields: field.fields,
rootRelationsToBuild,
@@ -316,8 +314,6 @@ export const traverseFields = ({
}
case 'blocks': {
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
field.blocks.forEach((block) => {
const blockTableName = `${rootTableName}_blocks_${toSnakeCase(block.slug)}`
if (!adapter.tables[blockTableName]) {
@@ -347,7 +343,7 @@ export const traverseFields = ({
adapter,
baseColumns,
baseExtraConfig,
disableNotNull: disableNotNullFromHere,
disableNotNull,
disableUnique,
fields: block.fields,
rootRelationsToBuild,
@@ -432,8 +428,6 @@ export const traverseFields = ({
break
}
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
const {
hasLocalizedField: groupHasLocalizedField,
hasLocalizedManyNumberField: groupHasLocalizedManyNumberField,
@@ -444,7 +438,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix: `${columnName}_`,
columns,
disableNotNull: disableNotNullFromHere,
disableNotNull,
disableUnique,
fieldPrefix: `${fieldName}_`,
fields: field.fields,
@@ -469,8 +463,6 @@ export const traverseFields = ({
}
case 'tabs': {
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
const {
hasLocalizedField: tabHasLocalizedField,
hasLocalizedManyNumberField: tabHasLocalizedManyNumberField,
@@ -481,7 +473,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix,
columns,
disableNotNull: disableNotNullFromHere,
disableNotNull,
disableUnique,
fieldPrefix,
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
@@ -508,7 +500,6 @@ export const traverseFields = ({
case 'row':
case 'collapsible': {
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
const {
hasLocalizedField: rowHasLocalizedField,
hasLocalizedManyNumberField: rowHasLocalizedManyNumberField,
@@ -519,7 +510,7 @@ export const traverseFields = ({
buildRelationships,
columnPrefix,
columns,
disableNotNull: disableNotNullFromHere,
disableNotNull,
disableUnique,
fieldPrefix,
fields: field.fields,

View File

@@ -1,6 +1,6 @@
{
"name": "payload",
"version": "2.0.7",
"version": "2.0.5",
"description": "Node, React and MongoDB Headless CMS and Application Framework",
"license": "MIT",
"main": "./dist/index.js",
@@ -187,6 +187,7 @@
"file-loader": "6.2.0",
"form-data": "3.0.1",
"get-port": "5.1.1",
"graphql-request": "6.1.0",
"mini-css-extract-plugin": "1.6.2",
"node-fetch": "2.6.12",
"nodemon": "3.0.1",
@@ -207,7 +208,8 @@
"webpack": "^5.78.0"
},
"engines": {
"node": ">=14"
"node": ">=14",
"pnpm": ">=8"
},
"files": [
"bin.js",

View File

@@ -6,13 +6,13 @@ import { toast } from 'react-toastify'
import type { Props } from './types'
import useDebounce from '../../../hooks/useDebounce'
import { formatTimeToNow } from '../../../utilities/formatDate'
import { useAllFormFields, useFormModified } from '../../forms/Form/context'
import reduceFieldsToValues from '../../forms/Form/reduceFieldsToValues'
import { useConfig } from '../../utilities/Config'
import { useDocumentInfo } from '../../utilities/DocumentInfo'
import { useLocale } from '../../utilities/Locale'
import './index.scss'
const baseClass = 'autosave'
const Autosave: React.FC<Props> = ({ id, collection, global, publishedDocUpdatedAt }) => {
@@ -163,7 +163,7 @@ const Autosave: React.FC<Props> = ({ id, collection, global, publishedDocUpdated
{!saving && lastSaved && (
<React.Fragment>
{t('lastSavedAgo', {
distance: formatTimeToNow(lastSaved, i18n.language),
distance: Math.round((Number(new Date(lastSaved)) - Number(new Date())) / 1000 / 60),
})}
</React.Fragment>
)}

View File

@@ -28,10 +28,10 @@
gap: var(--base);
padding-bottom: 1px;
z-index: 1;
height: var(--doc-controls-height);
}
&__content {
height: var(--doc-controls-height);
display: flex;
align-items: center;
flex-grow: 1;
@@ -140,21 +140,21 @@
// On mobile, only stick the controls to the top
// The timestamps and meta can scroll past
// The same container needs to the sticky, though
// So we use a static height with a negative top equal to the meta height plus top padding
top: calc(var(--base) * -2);
// So we use a static height with a negative top
top: calc(var(--doc-controls-height) * -1);
padding-right: 0;
padding-left: 0;
&__wrapper {
flex-direction: column;
gap: 0;
height: unset;
}
&__content {
width: 100%;
align-items: flex-start;
padding-top: calc(var(--base) / 2);
overflow: auto;
height: calc(var(--base) * 2);
// this container has a fixed height
// this means the scrollbar (when present) overlaps the content
@@ -167,52 +167,26 @@
width: auto;
gap: calc(var(--base) / 2);
margin-left: var(--gutter-h);
&::after {
content: '';
display: block;
position: sticky;
right: 0;
width: calc(var(--base) * 2);
height: var(--base);
background: linear-gradient(to right, transparent, var(--theme-bg));
flex-shrink: 0;
z-index: 1111;
pointer-events: none;
}
margin-right: var(--gutter-h);
}
&__controls-wrapper {
width: 100%;
transform: translate3d(0, 0, 0);
padding-right: var(--gutter-h);
justify-content: space-between;
height: var(--doc-controls-height);
border-top: 1px solid var(--theme-elevation-100);
padding: calc(var(--base) / 2) 0;
overflow: auto;
}
&__controls {
padding-left: var(--gutter-h);
overflow: auto;
margin-left: var(--gutter-h);
margin-right: var(--gutter-h);
}
// do not show scrollbar because the parent container has a static height
// this container has a gradient overlay as visual indication of `overflow: scroll`
&::-webkit-scrollbar {
display: none;
}
&::after {
content: '';
display: block;
position: sticky;
right: 0;
width: calc(var(--base) * 2);
height: calc(var(--base) * 1.5);
background: linear-gradient(to right, transparent, var(--theme-bg));
flex-shrink: 0;
z-index: 1111;
pointer-events: none;
}
&__popup {
// TODO: the container needs to overflow on mobile
// But the popup interferes with this because it requires overflow in order to be visible
// So we likely need to outright show the controls nested within the popup on mobile
display: none;
}
}
}

View File

@@ -2,8 +2,7 @@ import React, { Fragment } from 'react'
import { useTranslation } from 'react-i18next'
import type { CollectionPermission, GlobalPermission } from '../../../../auth'
import type { SanitizedCollectionConfig } from '../../../../collections/config/types'
import type { SanitizedGlobalConfig } from '../../../../globals/config/types'
import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from '../../../../exports/types'
import { formatDate } from '../../../utilities/formatDate'
import { useConfig } from '../../utilities/Config'

View File

@@ -1,5 +1,4 @@
import { useModal } from '@faceless-ui/modal'
import queryString from 'qs'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'react-toastify'
@@ -17,7 +16,6 @@ import X from '../../icons/X'
import { useAuth } from '../../utilities/Auth'
import { useConfig } from '../../utilities/Config'
import { DocumentInfoProvider, useDocumentInfo } from '../../utilities/DocumentInfo'
import { useFormQueryParams } from '../../utilities/FormQueryParams'
import { useLocale } from '../../utilities/Locale'
import RenderCustomComponent from '../../utilities/RenderCustomComponent'
import DefaultEdit from '../../views/collections/Edit/Default'
@@ -44,8 +42,6 @@ const Content: React.FC<DocumentDrawerProps> = ({
const [isOpen, setIsOpen] = useState(false)
const [collectionConfig] = useRelatedCollections(collectionSlug)
const config = useConfig()
const { formQueryParams } = useFormQueryParams()
const formattedQueryParams = queryString.stringify(formQueryParams)
const { admin: { components: { views: { Edit } = {} } = {} } = {} } = collectionConfig
@@ -121,8 +117,8 @@ const Content: React.FC<DocumentDrawerProps> = ({
const apiURL = id ? `${serverURL}${api}/${collectionSlug}/${id}?locale=${locale}` : null
const action = `${serverURL}${api}/${collectionSlug}${
isEditing ? `/${id}` : ''
}?${formattedQueryParams}`
id ? `/${id}` : ''
}?locale=${locale}&fallback-locale=null`
const hasSavePermission =
(isEditing && docPermissions?.update?.permission) ||

View File

@@ -17,24 +17,6 @@
padding: 0;
overflow: auto;
// this container has a gradient overlay as visual indication of `overflow: scroll`
&::-webkit-scrollbar {
display: none;
}
&::after {
content: '';
display: block;
position: sticky;
right: 0;
width: calc(var(--base) * 2);
height: calc(var(--base) * 2);
background: linear-gradient(to right, transparent, var(--theme-bg));
flex-shrink: 0;
z-index: 1111;
pointer-events: none;
}
&__tabs {
padding: 0;
margin-left: var(--gutter-h);

View File

@@ -35,6 +35,11 @@ $header-height: base(5);
text-wrap: nowrap;
}
&__cancel,
&__save {
width: 50%;
}
&__toolWrap {
display: flex;
justify-content: flex-end;

View File

@@ -50,13 +50,14 @@ export const EditUpload: React.FC<{
y: uploadEdits?.focalPoint?.y || 50,
})
const [checkBounds, setCheckBounds] = useState<boolean>(false)
const [originalHeight, setOriginalHeight] = useState<number>(0)
const [originalWidth, setOriginalWidth] = useState<number>(0)
const focalWrapRef = useRef<HTMLDivElement | undefined>()
const imageRef = useRef<HTMLImageElement | undefined>()
const cropRef = useRef<HTMLDivElement | undefined>()
const originalHeight = imageRef.current ? imageRef.current.naturalHeight : 0
const originalWidth = imageRef.current ? imageRef.current.naturalWidth : 0
const fineTuneCrop = ({ dimension, value }: { dimension: 'height' | 'width'; value: string }) => {
const intValue = parseInt(value)
if (dimension === 'width' && intValue >= originalWidth) return null
@@ -151,15 +152,7 @@ export const EditUpload: React.FC<{
return <div className={`${baseClass}__crop-window`} ref={cropRef} />
}}
>
<img
alt={t('upload:setCropArea')}
onLoad={(e) => {
setOriginalHeight(e.currentTarget.naturalHeight)
setOriginalWidth(e.currentTarget.naturalWidth)
}}
ref={imageRef}
src={fileSrcToUse}
/>
<img alt={t('upload:setCropArea')} ref={imageRef} src={fileSrcToUse} />
</ReactCrop>
) : (
<img alt={t('upload:setFocalPoint')} ref={imageRef} src={fileSrcToUse} />

View File

@@ -14,7 +14,7 @@
}
&__preview {
max-height: calc(100% - base(6));
max-height: calc(100% - base(4));
padding: base(1.5) base(1.5) base(1.5) var(--gutter-h);
object-fit: contain;
}

View File

@@ -28,8 +28,8 @@ const PreviewSizes: React.FC<{
doc?: Data & {
sizes?: FileSizes
}
imageCacheTag?: string
}> = ({ collection, doc, imageCacheTag }) => {
updatedAt?: string
}> = ({ collection, doc, updatedAt }) => {
const {
upload: { imageSizes, staticURL },
} = collection
@@ -39,15 +39,20 @@ const PreviewSizes: React.FC<{
const [selectedSize, setSelectedSize] = useState<null | string>(
orderedSizes?.[imageSizes[0]?.name]?.filename ? imageSizes[0]?.name : null,
)
const [appendUrl, setAppendUrl] = useState<boolean>(false)
const generateImageUrl = (filename) => {
return `${staticURL}/${filename}${imageCacheTag ? `?${imageCacheTag}` : ''}`
const query = appendUrl ? `?${Date.now()}` : ''
return `${staticURL}/${filename}${query}`
}
useEffect(() => {
setOrderedSizes(sortSizes(sizes, imageSizes))
}, [sizes, imageSizes, imageCacheTag])
}, [sizes, imageSizes, updatedAt])
const mainPreviewSrc = generateImageUrl(`${orderedSizes[selectedSize]?.filename}`)
useEffect(() => {
setAppendUrl(true)
}, [updatedAt])
return (
<div className={baseClass}>
@@ -56,15 +61,17 @@ const PreviewSizes: React.FC<{
<div className={`${baseClass}__sizeName`}>{selectedSize}</div>
<Meta {...(selectedSize && orderedSizes[selectedSize])} staticURL={staticURL} />
</div>
<img alt={doc.filename} className={`${baseClass}__preview`} src={mainPreviewSrc} />
<img
alt={doc.filename}
className={`${baseClass}__preview`}
src={generateImageUrl(`${orderedSizes[selectedSize]?.filename}`)}
/>
</div>
<div className={`${baseClass}__listWrap`}>
<div className={`${baseClass}__list`}>
{Object.entries(orderedSizes).map(([key, val]) => {
const selected = selectedSize === key
const previewSrc = generateImageUrl(val.filename)
if (previewSrc) {
if (val?.filename) {
return (
<div
className={[`${baseClass}__sizeOption`, selected && `${baseClass}--selected`]
@@ -81,7 +88,7 @@ const PreviewSizes: React.FC<{
tabIndex={0}
>
<div className={`${baseClass}__image`}>
<img alt={val.filename} src={previewSrc} />
<img alt={val.filename} src={generateImageUrl(val.filename)} />
</div>
<div className={`${baseClass}__sizeMeta`}>
<div className={`${baseClass}__sizeName`}>{key}</div>

View File

@@ -25,9 +25,12 @@ const Thumbnail: React.FC<Props> = (props) => {
const classes = [baseClass, `${baseClass}--size-${size || 'medium'}`, className].join(' ')
useEffect(() => {
if (thumbnailSRC) {
if (doc && collection && thumbnailSRC) {
setSrc(`${thumbnailSRC}${imageCacheTag ? `?${imageCacheTag}` : ''}`)
}
if (fileSrc) {
setSrc(fileSrc)
}
}, [doc, collection, thumbnailSRC, fileSrc, imageCacheTag])
return (

View File

@@ -297,7 +297,7 @@ const BlocksField: React.FC<Props> = (props) => {
</DrawerToggler>
<BlocksDrawer
addRow={addRow}
addRowIndex={rows?.length || 0}
addRowIndex={value || 0}
blocks={blocks}
drawerSlug={drawerSlug}
labels={labels}

View File

@@ -52,7 +52,7 @@
position: sticky;
top: var(--doc-controls-height);
width: 33.33%;
height: calc(100vh - var(--doc-controls-height));
height: 100%;
}
&__sidebar {

View File

@@ -56,7 +56,7 @@
position: sticky;
top: var(--doc-controls-height);
width: 33.33%;
height: calc(100vh - var(--doc-controls-height));
height: 100%;
}
&__sidebar {

View File

@@ -32,6 +32,7 @@ export const DefaultCollectionEdit: React.FC<CollectionEditViewProps> = (props)
internalState,
isEditing,
permissions,
updatedAt,
} = props
const { auth, fields, upload } = collection
@@ -96,7 +97,9 @@ export const DefaultCollectionEdit: React.FC<CollectionEditViewProps> = (props)
verify={auth.verify}
/>
)}
{upload && <Upload collection={collection} internalState={internalState} />}
{upload && (
<Upload collection={collection} internalState={internalState} updatedAt={updatedAt} />
)}
<RenderFields
className={`${baseClass}__fields`}
fieldSchema={fields}

View File

@@ -201,7 +201,7 @@ export const Upload: React.FC<Props> = (props) => {
slug={sizePreviewSlug}
title={t('upload:sizesFor', { label: doc?.filename })}
>
<PreviewSizes collection={collection} doc={doc} />
<PreviewSizes collection={collection} doc={doc} updatedAt={updatedAt} />
</Drawer>
)}
</div>

View File

@@ -46,7 +46,7 @@
@include mid-break {
--gutter-h: #{base(2)};
--app-header-height: calc(var(--base) * 2);
--doc-controls-height: calc(var(--base) * 2.5);
--doc-controls-height: calc(var(--base) * 1.5);
// set to xs-breakpoint to achieve a seamless transition to full screen
--nav-width: var(--breakpoint-xs-width);
}

View File

@@ -1,4 +1,4 @@
import { format, formatDistanceToNow } from 'date-fns'
import { format } from 'date-fns'
import * as Locale from 'date-fns/locale'
import { getSupportedDateLocale } from './getSupportedDateLocale'
@@ -12,12 +12,3 @@ export const formatDate = (
const currentLocale = Locale[getSupportedDateLocale(locale)]
return format(theDate, pattern, { locale: currentLocale })
}
export const formatTimeToNow = (
date: Date | number | string | undefined,
locale?: string,
): string => {
const theDate = new Date(date)
const currentLocale = Locale[getSupportedDateLocale(locale)]
return formatDistanceToNow(theDate, { locale: currentLocale })
}

View File

@@ -18,18 +18,16 @@ export {
*/
useWatchForm,
} from '../../admin/components/forms/Form/context'
export { createNestedFieldPath } from '../../admin/components/forms/Form/createNestedFieldPath'
export { default as getSiblingData } from '../../admin/components/forms/Form/getSiblingData'
export { default as reduceFieldsToValues } from '../../admin/components/forms/Form/reduceFieldsToValues'
export { default as Label } from '../../admin/components/forms/Label'
export { default as RenderFields } from '../../admin/components/forms/RenderFields'
export { default as Submit } from '../../admin/components/forms/Submit'
export { default as Submit } from '../../admin/components/forms/Submit'
export { default as FormSubmit } from '../../admin/components/forms/Submit'
export { fieldTypes } from '../../admin/components/forms/field-types'
export { default as Checkbox } from '../../admin/components/forms/field-types/Checkbox'
export { default as Collapsible } from '../../admin/components/forms/field-types/Collapsible'

View File

@@ -1,7 +1,7 @@
export { buildConfig } from '../config/build'
export * from '../config/types'
export { type FieldTypes } from '../admin/components/forms/field-types'
export { type FieldTypes, fieldTypes } from '../admin/components/forms/field-types'
export { defaults } from '../config/defaults'
export { sanitizeConfig } from '../config/sanitize'
export { baseBlockFields } from '../fields/baseFields/baseBlockFields'

View File

@@ -1,11 +1,10 @@
export { withMergedProps } from '../admin/components/utilities/WithMergedProps'
export { extractTranslations } from '../translations/extractTranslations'
export { i18nInit } from '../translations/init'
export { combineMerge } from '../utilities/combineMerge'
export { configToJSONSchema, entityToJSONSchema } from '../utilities/configToJSONSchema'
export { createArrayFromCommaDelineated } from '../utilities/createArrayFromCommaDelineated'
export { deepCopyObject } from '../utilities/deepCopyObject'
export { deepMerge } from '../utilities/deepMerge'
export { default as flattenTopLevelFields } from '../utilities/flattenTopLevelFields'

View File

@@ -67,7 +67,6 @@ export type FilterOptionsProps<T = any> = {
export type FilterOptions<T = any> =
| ((options: FilterOptionsProps<T>) => Promise<Where> | Where)
| Where
| null
type Admin = {
className?: string

View File

@@ -258,18 +258,14 @@ const validateFilterOptions: Validate = async (
})
if (valueIDs.length > 0) {
const findWhere = {
and: [{ id: { in: valueIDs } }],
}
if (optionFilter) findWhere.and.push(optionFilter)
const result = await payload.find({
collection,
depth: 0,
limit: 0,
pagination: false,
where: findWhere,
where: {
and: [{ id: { in: valueIDs } }, optionFilter],
},
})
options[collection] = result.docs.map((doc) => doc.id)
@@ -386,7 +382,7 @@ export const relationship: Validate<unknown, unknown, RelationshipField> = async
})
if (invalidRelationships.length > 0) {
return `This relationship field has the following invalid relationships: ${invalidRelationships
return `This field has the following invalid selections: ${invalidRelationships
.map((err, invalid) => {
return `${err} ${JSON.stringify(invalid)}`
})

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "المستند {{docStatus}} الحالي",
"draft": "مسودّة",
"draftSavedSuccessfully": "تمّ حفظ المسودّة بنجاح.",
"lastSavedAgo": "تم الحفظ آخر مرة قبل {{distance}}",
"lastSavedAgo": "آخر حفظ في {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "لم يتمّ العثور على نسخات أخرى",
"noRowsFound": "لم يتمّ العثور على {{label}}",
"preview": "معاينة",
@@ -368,4 +368,4 @@
"viewingVersions": "يتمّ استعراض النُّسَخ ل {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "يتمّ استعراض النُّسَخ للاعداد العامّ {{entityLabel}}"
}
}
}

View File

@@ -334,7 +334,7 @@
"currentDocumentStatus": "Cari {{docStatus}} sənədi",
"draft": "Qaralama",
"draftSavedSuccessfully": "Qaralama uğurla yadda saxlandı.",
"lastSavedAgo": "{{distance}} əvvəl son yadda saxlanıldı",
"lastSavedAgo": "Son yadda saxlama: {{distance, relativetime(minutes)}} əvvəl",
"noFurtherVersionsFound": "Başqa versiyalar tapılmadı",
"noRowsFound": "Heç bir {{label}} tapılmadı",
"preview": "Öncədən baxış",
@@ -369,4 +369,4 @@
"viewingVersions": "{{entityLabel}} {{documentTitle}} üçün versiyaları göstərir",
"viewingVersionsGlobal": "Qlobal {{entityLabel}} üçün versiyaları göstərir"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Сегашен статус на документа: {{docStatus}}",
"draft": "Чернова",
"draftSavedSuccessfully": "Чернова запазена успешно.",
"lastSavedAgo": "последно запазено преди {{distance}}",
"lastSavedAgo": "Последно запазен {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Не са открити повече версии",
"noRowsFound": "Не е открит {{label}}",
"preview": "Предварителен преглед",

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Současný {{docStatus}} dokument",
"draft": "Koncept",
"draftSavedSuccessfully": "Koncept úspěšně uložen.",
"lastSavedAgo": "Naposledy uloženo před {{distance}}",
"lastSavedAgo": "Naposledy uloženo {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Nenalezeny další verze",
"noRowsFound": "Nenalezen {{label}}",
"preview": "Náhled",
@@ -368,4 +368,4 @@
"viewingVersions": "Zobrazuji verze pro {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Zobrazuji verze pro globální {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Aktueller Dokumentenstatus: {{docStatus}}",
"draft": "Entwurf",
"draftSavedSuccessfully": "Entwurf erfolgreich gespeichert.",
"lastSavedAgo": "Zuletzt vor {{distance}} gespeichert",
"lastSavedAgo": "Zuletzt gespeichert {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Keine weiteren Versionen vorhanden",
"noRowsFound": "Kein {{label}} gefunden",
"preview": "Vorschau",

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Current {{docStatus}} document",
"draft": "Draft",
"draftSavedSuccessfully": "Draft saved successfully.",
"lastSavedAgo": "Last saved {{distance}} ago",
"lastSavedAgo": "Last saved {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "No further versions found",
"noRowsFound": "No {{label}} found",
"preview": "Preview",

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Documento {{docStatus}} actual",
"draft": "Borrador",
"draftSavedSuccessfully": "Borrador guardado con éxito.",
"lastSavedAgo": "Guardado por última vez hace {{distance}}",
"lastSavedAgo": "Último guardado {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "No se encontraron más versiones",
"noRowsFound": "No encontramos {{label}}",
"preview": "Previsualizar",
@@ -368,4 +368,4 @@
"viewingVersions": "Viendo versiones para {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Viendo versiones para el global {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "جاری {{docStatus}} سند",
"draft": "پیش‌نویس",
"draftSavedSuccessfully": "پیش‌نویس با موفقیت ذخیره شد.",
"lastSavedAgo": "آخرین بار {{distance}} پیش ذخیره شد",
"lastSavedAgo": "آخرین ذخیره‌سازی {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "نگارش دیگری یافت نشد",
"noRowsFound": "هیچ {{label}} یافت نشد",
"preview": "پیش‌نمایش",
@@ -368,4 +368,4 @@
"viewingVersions": "مشاهده نگارش‌ها برای {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "مشاهده نگارش‌های کلی {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Document {{docStatus}} actuel",
"draft": "Brouillon",
"draftSavedSuccessfully": "Brouillon enregistré avec succès.",
"lastSavedAgo": "Dernière sauvegarde il y a {{distance}}",
"lastSavedAgo": "Enregistré il y a de cela {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Aucune autre version trouvée",
"noRowsFound": "Aucun(e) {{label}} trouvé(e)",
"preview": "Aperçu",
@@ -368,4 +368,4 @@
"viewingVersions": "Affichage des versions de ou du {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Affichage des versions globales de ou du {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Trenutni {{docStatus}} dokumenta",
"draft": "Nacrt",
"draftSavedSuccessfully": "Nacrt uspješno spremljen.",
"lastSavedAgo": "Zadnji put spremljeno prije {{distance}",
"lastSavedAgo": "Zadnje spremljeno prije {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Nisu pronađene daljnje verzije",
"noRowsFound": "{{label}} nije pronađeno",
"preview": "Pregled",
@@ -368,4 +368,4 @@
"viewingVersions": "Pregled verzija za {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Pregled verzije za globalni {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Jelenlegi {{docStatus}} dokumentum",
"draft": "Piszkozat",
"draftSavedSuccessfully": "A piszkozat sikeresen mentve.",
"lastSavedAgo": "Utoljára mentve {{distance}} órája",
"lastSavedAgo": "Utoljára mentve {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "További verziók nem találhatók",
"noRowsFound": "Nem található {{label}}",
"preview": "Előnézet",
@@ -368,4 +368,4 @@
"viewingVersions": "A {{entityLabel}} {{documentTitle}} verzióinak megtekintése",
"viewingVersionsGlobal": "A globális {{entityLabel}} verzióinak megtekintése"
}
}
}

View File

@@ -334,7 +334,7 @@
"currentDocumentStatus": "Documento {{docStatus}} corrente",
"draft": "Bozza",
"draftSavedSuccessfully": "Bozza salvata con successo.",
"lastSavedAgo": "Ultimo salvataggio {{distance}} fa",
"lastSavedAgo": "Ultimo salvataggio {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Non sono state trovate ulteriori versioni",
"noRowsFound": "Nessun {{label}} trovato",
"preview": "Anteprima",
@@ -369,4 +369,4 @@
"viewingVersions": "Visualizzazione delle versioni per {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Visualizzazione delle versioni per {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "現在の {{docStatus}} データ",
"draft": "ドラフト",
"draftSavedSuccessfully": "下書きは正常に保存されました。",
"lastSavedAgo": "{{distance}}前に最後に保存されました",
"lastSavedAgo": "最新の保存 {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "その他のバージョンは見つかりませんでした。",
"noRowsFound": "{{label}} は未設定です",
"preview": "プレビュー",
@@ -368,4 +368,4 @@
"viewingVersions": "表示バージョン: {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "表示バージョン: グローバルな {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "လက်ရှိ {{docStatus}} ဖိုင်",
"draft": "မူကြမ်း",
"draftSavedSuccessfully": "မူကြမ်းကို အောင်မြင်စွာ သိမ်းဆည်းပြီးပါပြီ။",
"lastSavedAgo": "နောက်ဆုံး သိမ်းချက် {{distance}} ကြာပြီး",
"lastSavedAgo": "နောက်ဆုံး ပြင်ဆင်ခဲ့သည်။ {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "နောက်ထပ်ဗားရှင်းများ မတွေ့ပါ။",
"noRowsFound": "{{label}} အားမတွေ့ပါ။",
"preview": "နမူနာပြရန်",
@@ -368,4 +368,4 @@
"viewingVersions": "{{entityLabel}} {{documentTitle}} အတွက် ဗားရှင်းများကို ကြည့်ရှုခြင်း",
"viewingVersionsGlobal": "`ဂလိုဘယ်ဆိုင်ရာ {{entityLabel}} အတွက် ဗားရှင်းများကို ကြည့်ရှုနေသည်"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Nåværende {{docStatus}} dokument",
"draft": "Utkast",
"draftSavedSuccessfully": "Utkast lagret.",
"lastSavedAgo": "Sist lagret {{distance}} siden",
"lastSavedAgo": "Sist lagret {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Ingen flere versjoner funnet",
"noRowsFound": "Ingen {{label}} funnet",
"preview": "Forhåndsvisning",
@@ -368,4 +368,4 @@
"viewingVersions": "Viser versjoner for {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Viser versjoner for den globale variabelen {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Huidig {{docStatus}} document",
"draft": "Concept",
"draftSavedSuccessfully": "Concept succesvol bewaard.",
"lastSavedAgo": "Laatst opgeslagen {{distance}} geleden",
"lastSavedAgo": "Laatst bewaard {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Geen verdere versies gevonden",
"noRowsFound": "Geen {{label}} gevonden",
"preview": "Voorbeeld",
@@ -368,4 +368,4 @@
"viewingVersions": "Bekijk versies voor {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Bekijk versies voor global {{entityLabel}}"
}
}
}

View File

@@ -334,7 +334,7 @@
"currentDocumentStatus": "Bieżący status {{docStatus}} dokumentu",
"draft": "Szkic",
"draftSavedSuccessfully": "Wersja robocza została pomyślnie zapisana.",
"lastSavedAgo": "Ostatnio zapisane {{distance}} temu",
"lastSavedAgo": "Ostatnio zapisano {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Nie znaleziono dalszych wersji",
"noRowsFound": "Nie znaleziono {{label}}",
"preview": "Podgląd",
@@ -369,4 +369,4 @@
"viewingVersions": "Przeglądanie wersji {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Przeglądanie wersji dla globalnej kolekcji {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Documento {{docStatus}} atual",
"draft": "Rascunho",
"draftSavedSuccessfully": "Rascunho salvo com sucesso.",
"lastSavedAgo": "Última gravação há {{distance}}",
"lastSavedAgo": "Salvo pela última vez {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Nenhuma outra versão encontrada",
"noRowsFound": "Nenhum(a) {{label}} encontrado(a)",
"preview": "Pré-visualização",
@@ -368,4 +368,4 @@
"viewingVersions": "Visualizando versões para o/a {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Visualizando versões para o global {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Documentul {{docStatus}} curent",
"draft": "Proiect",
"draftSavedSuccessfully": "Proiect salvat cu succes.",
"lastSavedAgo": "Ultima salvare acum {{distance}}",
"lastSavedAgo": "Ultima salvare {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Nu s-au găsit alte versiuni",
"noRowsFound": "Nu s-a găsit niciun {{label}}",
"preview": "Previzualizare",
@@ -368,4 +368,4 @@
"viewingVersions": "Vizualizarea versiunilor pentru {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Vizualizarea versiunilor pentru globala {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Текущий статус {{docStatus}} документа",
"draft": "Черновик",
"draftSavedSuccessfully": "Черновик успешно сохранен.",
"lastSavedAgo": "Последний раз сохранено {{distance}} назад",
"lastSavedAgo": "Последнее сохранение было {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Другие версии не найдены",
"noRowsFound": "Не найдено {{label}}",
"preview": "Предпросмотр",

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Nuvarande {{docStatus}} dokument",
"draft": "Utkast",
"draftSavedSuccessfully": "Utkastet sparades framgångsrikt.",
"lastSavedAgo": "Senast sparad för {{distance}} sedan",
"lastSavedAgo": "Sparades senast {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Inga fler versioner hittades",
"noRowsFound": "Inga {{label}} hittades",
"preview": "Förhandsvisa",
@@ -368,4 +368,4 @@
"viewingVersions": "Visar versioner för {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "Visa versioner för den globala {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "เอกสารปัจจุบัน",
"draft": "ฉบับร่าง",
"draftSavedSuccessfully": "บันทึกร่างสำเร็จ",
"lastSavedAgo": "บันทึกครั้งล่าสุด {{distance}} ที่ผ่านมา",
"lastSavedAgo": "บันทึกล่าสุดเมื่อ {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "ไม่พบเวอร์ชันอื่น ๆ",
"noRowsFound": "ไม่พบ {{label}}",
"preview": "ตัวอย่าง",
@@ -368,4 +368,4 @@
"viewingVersions": "กำลังดูเวอร์ชันของ {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "กำลังดูเวอร์ชันของ global {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Şu an {{docStatus}} döküman",
"draft": "Taslak",
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
"lastSavedAgo": "Son kaydedildi {{distance}} önce",
"lastSavedAgo": "Son kaydedilme: {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Başka sürüm bulunamadı.",
"noRowsFound": "{{label}} bulunamadı",
"preview": "Önizleme",
@@ -368,4 +368,4 @@
"viewingVersions": "{{entityLabel}} {{documentTitle}} için sürümler gösteriliyor",
"viewingVersionsGlobal": "`Global {{entityLabel}} için sürümler gösteriliyor"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Поточний статус {{docStatus}} документа",
"draft": "Чернетка",
"draftSavedSuccessfully": "Чернетка успішно збережена.",
"lastSavedAgo": "Останній раз збережено {{distance}} тому",
"lastSavedAgo": "Останній запис {{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "Інших версій не знайдено",
"noRowsFound": "Не знайдено {{label}}",
"preview": "Попередній перегляд",

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "Trạng thái tài liệu hiện tại: {{docStatus}}",
"draft": "Bản nháp",
"draftSavedSuccessfully": "Bản nháp đã được lưu thành công.",
"lastSavedAgo": "Lần lưu cuối cùng {{distance}} trước đây",
"lastSavedAgo": "Bản lưu mới nhất: {{distance, relativetime(minutes)}} trước",
"noFurtherVersionsFound": "Không tìm thấy phiên bản cũ hơn",
"noRowsFound": "Không tìm thấy: {{label}}",
"preview": "Bản xem trước",
@@ -368,4 +368,4 @@
"viewingVersions": "Xem những phiên bản của {{entityLabel}} {{documentTitle}}",
"viewingVersionsGlobal": "`Xem những phiên bản toàn thể (global) của {{entityLabel}}"
}
}
}

View File

@@ -333,7 +333,7 @@
"currentDocumentStatus": "当前{{docStatus}}文件",
"draft": "草稿",
"draftSavedSuccessfully": "草稿成功保存。",
"lastSavedAgo": "次保存{{distance}}之前",
"lastSavedAgo": "最后一次保存{{distance, relativetime(minutes)}}",
"noFurtherVersionsFound": "没有发现其他版本",
"noRowsFound": "没有发现{{label}}",
"preview": "预览",
@@ -368,4 +368,4 @@
"viewingVersions": "正在查看{{entityLabel}} {{documentTitle}}的版本",
"viewingVersionsGlobal": "正在查看全局{{entityLabel}}的版本"
}
}
}

View File

@@ -217,11 +217,11 @@ export default async function resizeAndTransformImageSizes({
const maxOffsetX = Math.max(info.width - width, 0)
const maxOffsetY = Math.max(info.height - height, 0)
const focalPointX = Math.floor((info.width / 100) * focalPoint.x)
const focalPointY = Math.floor((info.height / 100) * focalPoint.y)
const focalPointX = Math.floor(info.width * focalPoint.x - width / 2)
const focalPointY = Math.floor(info.height * focalPoint.y - height / 2)
const offsetX = Math.min(Math.max(focalPointX - width / 2, 0), maxOffsetX)
const offsetY = Math.min(Math.max(focalPointY - height / 2, 0), maxOffsetY)
const offsetX = Math.min(Math.max(focalPointX, 0), maxOffsetX)
const offsetY = Math.min(Math.max(focalPointY, 0), maxOffsetY)
resized = resized.extract({
height,

View File

@@ -1,37 +0,0 @@
/** @type {import('prettier').Config} */
module.exports = {
extends: ['@payloadcms'],
overrides: [
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
parserOptions: {
project: ['./tsconfig.json'],
tsconfigRootDir: __dirname,
},
root: true,
}

View File

@@ -1,3 +0,0 @@
module.exports = {
extends: ['@payloadcms'],
}

View File

@@ -1,6 +0,0 @@
node_modules
.env
dist
build
.DS_Store
package-lock.json

View File

@@ -1,10 +0,0 @@
.tmp
**/.git
**/.hg
**/.pnp.*
**/.svn
**/.yarn/**
**/build
**/dist/**
**/node_modules
**/temp

View File

@@ -1,15 +0,0 @@
{
"$schema": "https://json.schemastore.org/swcrc",
"sourceMaps": "inline",
"jsc": {
"target": "esnext",
"parser": {
"syntax": "typescript",
"tsx": true,
"dts": true
}
},
"module": {
"type": "commonjs"
}
}

View File

@@ -1,248 +0,0 @@
# Payload Nested Docs Plugin
[![NPM](https://img.shields.io/npm/v/@payloadcms/plugin-nested-docs)](https://www.npmjs.com/package/@payloadcms/plugin-nested-docs)
A plugin for [Payload CMS](https://github.com/payloadcms/payload) to easily allow for documents to be nested inside one another.
Core features:
- Allows for [parent/child](#parent) relationships between documents
- Automatically populates [breadcrumbs](#breadcrumbs) data
## Installation
```bash
yarn add @payloadcms/plugin-nested-docs
# OR
npm i @payloadcms/plugin-nested-docs
```
## Basic Usage
In the `plugins` array of your [Payload config](https://payloadcms.com/docs/configuration/overview), call the plugin with [options](#options):
```js
import { buildConfig } from "payload/config";
import nestedDocs from "@payloadcms/plugin-nested-docs";
const config = buildConfig({
collections: [
{
slug: "pages",
fields: [
{
name: "title",
type: "text",
},
{
name: "slug",
type: "text",
},
],
},
],
plugins: [
nestedDocs({
collections: ["pages"],
generateLabel: (_, doc) => doc.title,
generateURL: (docs) =>
docs.reduce((url, doc) => `${url}/${doc.slug}`, ""),
}),
],
});
export default config;
```
### Fields
#### Parent
The `parent` relationship field is automatically added to every document which allows editors to choose another document from the same collection to act as the direct parent.
#### Breadcrumbs
The `breadcrumbs` field is an array which dynamically populates all parent relationships of a document up to the top level. It does not store any data in the database, and instead, acts as a `virtual` field which is dynamically populated each time the document is loaded.
The `breadcrumbs` array stores the following fields:
- `label`
The label of the breadcrumb. This field is automatically set to either the `collection.admin.useAsTitle` (if defined) or is set to the `ID` of the document. You can also dynamically define the `label` by passing a function to the options property of [`generateLabel`](#generateLabel).
- `url`
The URL of the breadcrumb. By default, this field is undefined. You can manually define this field by passing a property called function to the plugin options property of [`generateURL`](#generateURL).
### Options
#### `collections`
An array of collections slugs to enable nested docs.
#### `generateLabel`
Each `breadcrumb` has a required `label` field. By default, its value will be set to the collection's `admin.useAsTitle` or fallback the the `ID` of the document.
You can also pass a function to dynamically set the `label` of your breadcrumb.
```js
{
plugins: [
...
nestedDocs({
...
generateLabel: (_, doc) => doc.title // NOTE: 'title' is a hypothetical field
})
]
```
The function takes two arguments and returns a string:
1. `breadcrumbs` - an array of the breadcrumbs up to that point
2. `currentDoc` - the current document being edited
#### `generateURL`
A function that allows you to dynamically generate each breadcrumb `url`. Each `breadcrumb` has an optional `url` field which is undefined by default. For example, you might want to format a full URL to contain all of the breadcrumbs up to that point, like `/about-us/company/our-team`.
```js
plugins: [
...
nestedDocs({
...
generateURL: (docs) => docs.reduce((url, doc) => `${url}/${doc.slug}`, ''), // NOTE: 'slug' is a hypothetical field
})
]
```
This function takes two arguments and returns a string:
1. `breadcrumbs` - an array of the breadcrumbs up to that point
1. `currentDoc` - the current document being edited
#### `parentFieldSlug`
When defined, the `parent` field will not be provided for you automatically, and instead, expects you to add your own `parent` field to each collection manually. This gives you complete control over where you put the field in your admin dashboard, etc. Set this property to the `name` of your custom field.
#### `breadcrumbsFieldSlug`
When defined, the `breadcrumbs` field will not be provided for you, and instead, expects your to add your own `breadcrumbs` field to each collection manually. Set this property to the `name` of your custom field.
> Note - if you opt out of automatically being provided a `parent` or `breadcrumbs` field, you need to make sure that both fields are placed at the top-level of your document. They cannot exist within any nested data structures like a `group`, `array`, or `blocks`.
## Overrides
You can also extend the built-in `parent` and `breadcrumbs` fields per collection by using the `createParentField` and `createBreadcrumbField` methods. They will merge your customizations overtop the plugin's base field configurations.
```js
import { CollectionConfig } from "payload/types";
import createParentField from "@payloadcms/plugin-nested-docs/fields/parent";
import createBreadcrumbsField from "@payloadcms/plugin-nested-docs/fields/breadcrumbs";
const examplePageConfig: CollectionConfig = {
slug: "pages",
fields: [
createParentField(
// First argument is equal to the slug of the collection
// that the field references
"pages",
// Second argument is equal to field overrides that you specify,
// which will be merged into the base parent field config
{
admin: {
position: "sidebar",
},
// Note: if you override the `filterOptions` of the `parent` field,
// be sure to continue to prevent the document from referencing itself as the parent like this:
// filterOptions: ({ id }) => ({ id: {not_equals: id }})`
}
),
createBreadcrumbsField(
// First argument is equal to the slug of the collection
// that the field references
"pages",
// Argument equal to field overrides that you specify,
// which will be merged into the base `breadcrumbs` field config
{
label: "Page Breadcrumbs",
}
),
],
};
```
## Localization
This plugin supports localization by default. If the `localization` property is set in your Payload config, the `breadcrumbs` field is automatically localized. For more details on how localization works in Payload, see the [Localization](https://payloadcms.com/docs/localization/overview) docs.
## TypeScript
All types can be directly imported:
```js
import {
PluginConfig,
GenerateURL,
GenerateLabel,
} from "@payloadcms/plugin-nested-docs/types";
```
## Development
To actively develop or debug this plugin you can either work directly within the demo directory of this repo, or link your own project.
1. #### Internal Demo
This repo includes a fully working, self-seeding instance of Payload that installs the plugin directly from the source code. This is the easiest way to get started. To spin up this demo, follow these steps:
1. First clone the repo
1. Then, `cd YOUR_PLUGIN_REPO && yarn && cd demo && yarn && yarn dev`
1. Now open `http://localhost:3000/admin` in your browser
1. Enter username `dev@payloadcms.com` and password `test`
That's it! Changes made in `./src` will be reflected in your demo. Keep in mind that the demo database is automatically seeded on every startup, any changes you make to the data get destroyed each time you reboot the app.
1. #### Linked Project
You can alternatively link your own project to the source code:
1. First clone the repo
1. Then, `cd YOUR_PLUGIN_REPO && yarn && cd demo && cp env.example .env && yarn && yarn dev`
1. Now `cd` back into your own project and run, `yarn link @payloadcms/plugin-nested-docs`
1. If this plugin using React in any way, continue to the next step. Otherwise skip to step 7.
1. From your own project, `cd node_modules/react && yarn link && cd ../react-dom && yarn link && cd ../../`
1. Then, `cd YOUR_PLUGIN_REPO && yarn link react react-dom`
All set! You can now boot up your own project as normal, and your local copy of the plugin source code will be used. Keep in mind that changes to the source code require a rebuild, `yarn build`.
You might also need to alias these modules in your Webpack config. To do this, open your project's Payload config and add the following:
```js
import { buildConfig } from "payload/config";
export default buildConfig({
admin: {
webpack: (config) => ({
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
react: path.join(__dirname, "../node_modules/react"),
"react-dom": path.join(__dirname, "../node_modules/react-dom"),
payload: path.join(__dirname, "../node_modules/payload"),
"@payloadcms/plugin-nested-docs": path.join(
__dirname,
"../../payload/plugin-nested-docs/src"
),
},
},
}),
},
});
```
## Screenshots

View File

@@ -1,2 +0,0 @@
export * from './dist/fields/breadcrumbs';
export * from './dist/fields/parent';

View File

@@ -1,7 +0,0 @@
const breadcrumbs = require('./dist/fields/breadcrumbs');
const parent = require('./dist/fields/parent');
module.exports = {
breadcrumbs,
parent
};

View File

@@ -1,42 +0,0 @@
{
"name": "@payloadcms/plugin-nested-docs",
"version": "1.0.8",
"description": "The official Nested Docs plugin for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",
"homepage": "https://payloadcms.com",
"author": "Payload CMS, Inc.",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"build": "pnpm copyfiles && pnpm build:swc && pnpm build:types",
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"clean": "rimraf {dist,*.tsbuildinfo}",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
"prepublishOnly": "pnpm clean && pnpm build"
},
"devDependencies": {
"@payloadcms/eslint-config": "workspace:*",
"payload": "workspace:*"
},
"exports": {
".": {
"default": "./src/index.ts",
"types": "./src/index.ts"
}
},
"publishConfig": {
"exports": null,
"main": "./dist/index.js",
"registry": "https://registry.npmjs.org/",
"types": "./dist/index.d.ts"
},
"files": [
"dist",
"fields.js",
"fields.d.ts",
"types.js",
"types.d.ts"
]
}

View File

@@ -1,49 +0,0 @@
import type { ArrayField, Field } from 'payload/types'
const createBreadcrumbsField = (
relationTo: string,
overrides: Partial<ArrayField> = {},
): Field => ({
name: 'breadcrumbs',
type: 'array',
localized: true,
fields: [
{
name: 'doc',
type: 'relationship',
relationTo,
maxDepth: 0,
admin: {
disabled: true,
},
},
{
type: 'row',
fields: [
{
name: 'url',
label: 'URL',
type: 'text',
admin: {
width: '50%',
},
},
{
name: 'label',
type: 'text',
admin: {
width: '50%',
},
},
],
},
...(overrides?.fields || []),
],
admin: {
readOnly: true,
...(overrides?.admin || {}),
},
...(overrides || {}),
})
export default createBreadcrumbsField

View File

@@ -1,32 +0,0 @@
import { RelationshipField } from 'payload/types'
const createParentField = (
relationTo: string,
overrides?: Partial<
RelationshipField & {
hasMany: false
}
>,
): RelationshipField => ({
name: 'parent',
relationTo,
type: 'relationship',
maxDepth: 1,
filterOptions: ({ id }) => {
if (id) {
return {
id: { not_equals: id },
'breadcrumbs.doc': { not_in: [id] },
}
}
return null
},
admin: {
position: 'sidebar',
...(overrides?.admin || {}),
},
...(overrides || {}),
})
export default createParentField

View File

@@ -1,56 +0,0 @@
import type { CollectionAfterChangeHook, CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../types'
import populateBreadcrumbs from '../utilities/populateBreadcrumbs'
const resaveChildren =
(pluginConfig: PluginConfig, collection: CollectionConfig): CollectionAfterChangeHook =>
({ req: { payload, locale }, req, doc }) => {
const resaveChildrenAsync = async (): Promise<void> => {
const children = await payload.find({
req,
collection: collection.slug,
where: {
parent: {
equals: doc.id,
},
},
depth: 0,
locale,
})
try {
children.docs.forEach((child: any) => {
const updateAsDraft =
typeof collection.versions === 'object' &&
collection.versions.drafts &&
child._status !== 'published'
payload.update({
req,
id: child.id,
collection: collection.slug,
draft: updateAsDraft,
data: {
...child,
breadcrumbs: populateBreadcrumbs(req, pluginConfig, collection, child),
},
depth: 0,
locale,
})
})
} catch (err: unknown) {
payload.logger.error(
`Nested Docs plugin has had an error while re-saving a child document.`,
)
payload.logger.error(err)
}
}
// Non-blocking
resaveChildrenAsync()
return undefined
}
export default resaveChildren

View File

@@ -1,59 +0,0 @@
import type { CollectionAfterChangeHook, CollectionConfig } from 'payload/types'
import type { Breadcrumb } from '../types'
interface DocWithBreadcrumbs {
breadcrumbs: Breadcrumb[]
}
// This hook automatically re-saves a document after it is created
// so that we can build its breadcrumbs with the newly created document's ID.
const resaveSelfAfterCreate =
(collection: CollectionConfig): CollectionAfterChangeHook =>
async ({ req, doc, operation }) => {
const { payload, locale } = req
const { breadcrumbs = [] } = doc as DocWithBreadcrumbs
if (operation === 'create') {
const originalDocWithDepth0 = await payload.findByID({
req,
collection: collection.slug,
depth: 0,
id: doc.id,
})
const updateAsDraft =
typeof collection.versions === 'object' &&
collection.versions.drafts &&
doc._status !== 'published'
try {
await payload.update({
req,
collection: collection.slug,
id: doc.id,
locale,
depth: 0,
draft: updateAsDraft,
data: {
...originalDocWithDepth0,
breadcrumbs:
breadcrumbs?.map((crumb, i) => ({
...crumb,
doc: breadcrumbs.length === i + 1 ? doc.id : crumb.doc,
})) || [],
},
})
} catch (err: unknown) {
payload.logger.error(
`Nested Docs plugin has had an error while adding breadcrumbs during document creation.`,
)
payload.logger.error(err)
}
}
return undefined
}
export default resaveSelfAfterCreate

View File

@@ -1,49 +0,0 @@
import type { Plugin } from 'payload/config'
import createBreadcrumbsField from './fields/breadcrumbs'
import createParentField from './fields/parent'
import resaveChildren from './hooks/resaveChildren'
import resaveSelfAfterCreate from './hooks/resaveSelfAfterCreate'
import type { PluginConfig } from './types'
import populateBreadcrumbs from './utilities/populateBreadcrumbs'
const nestedDocs =
(pluginConfig: PluginConfig): Plugin =>
(config) => ({
...config,
collections: (config.collections || []).map((collection) => {
if (pluginConfig.collections.indexOf(collection.slug) > -1) {
const fields = [...(collection?.fields || [])]
if (!pluginConfig.parentFieldSlug) {
fields.push(createParentField(collection.slug))
}
if (!pluginConfig.breadcrumbsFieldSlug) {
fields.push(createBreadcrumbsField(collection.slug))
}
return {
...collection,
hooks: {
...(collection.hooks || {}),
beforeChange: [
async ({ req, data, originalDoc }) =>
populateBreadcrumbs(req, pluginConfig, collection, data, originalDoc),
...(collection?.hooks?.beforeChange || []),
],
afterChange: [
resaveChildren(pluginConfig, collection),
resaveSelfAfterCreate(collection),
...(collection?.hooks?.afterChange || []),
],
},
fields,
}
}
return collection
}),
})
export default nestedDocs

View File

@@ -1,23 +0,0 @@
export interface Breadcrumb {
url?: string
label: string
doc: string
}
export type GenerateURL = (
docs: Array<Record<string, unknown>>,
currentDoc: Record<string, unknown>,
) => string
export type GenerateLabel = (
docs: Array<Record<string, unknown>>,
currentDoc: Record<string, unknown>,
) => string
export interface PluginConfig {
collections: string[]
generateURL?: GenerateURL
generateLabel?: GenerateLabel
parentFieldSlug?: string
breadcrumbsFieldSlug?: string
}

View File

@@ -1,33 +0,0 @@
import type { CollectionConfig } from 'payload/types'
import type { Breadcrumb, PluginConfig } from '../types'
const formatBreadcrumb = (
pluginConfig: PluginConfig,
collection: CollectionConfig,
docs: Array<Record<string, unknown>>,
): Breadcrumb => {
let url: string | undefined = undefined
let label: string
const lastDoc = docs[docs.length - 1]
if (typeof pluginConfig?.generateURL === 'function') {
url = pluginConfig.generateURL(docs, lastDoc)
}
if (typeof pluginConfig?.generateLabel === 'function') {
label = pluginConfig.generateLabel(docs, lastDoc)
} else {
const useAsTitle = collection?.admin?.useAsTitle || 'id'
label = lastDoc[useAsTitle] as string
}
return {
label,
url,
doc: lastDoc.id as string,
}
}
export default formatBreadcrumb

View File

@@ -1,47 +0,0 @@
import type { CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../types'
const getParents = async (
req: any,
pluginConfig: PluginConfig,
collection: CollectionConfig,
doc: Record<string, unknown>,
docs: Array<Record<string, unknown>> = [],
): Promise<Array<Record<string, unknown>>> => {
const parent = doc[pluginConfig?.parentFieldSlug || 'parent']
let retrievedParent
if (parent) {
// If not auto-populated, and we have an ID
if (typeof parent === 'string' || typeof parent === 'number') {
retrievedParent = await req.payload.findByID({
req,
id: parent,
collection: collection.slug,
depth: 0,
disableErrors: true,
})
}
// If auto-populated
if (typeof parent === 'object') {
retrievedParent = parent
}
if (retrievedParent) {
if (retrievedParent.parent) {
return getParents(req, pluginConfig, collection, retrievedParent, [
retrievedParent,
...docs,
])
}
return [retrievedParent, ...docs]
}
}
return docs
}
export default getParents

View File

@@ -1,43 +0,0 @@
import type { CollectionConfig } from 'payload/types'
import type { PluginConfig } from '../types'
import formatBreadcrumb from './formatBreadcrumb'
import getParents from './getParents'
const populateBreadcrumbs = async (
req: any,
pluginConfig: PluginConfig,
collection: CollectionConfig,
data: any,
originalDoc?: any,
): Promise<any> => {
const newData = data
const breadcrumbDocs = [
...(await getParents(req, pluginConfig, collection, {
...originalDoc,
...data,
})),
]
const currentDocBreadcrumb = {
...originalDoc,
...data,
}
if (originalDoc?.id) {
currentDocBreadcrumb.id = originalDoc?.id
}
breadcrumbDocs.push(currentDocBreadcrumb)
const breadcrumbs = breadcrumbDocs.map((_, i) =>
formatBreadcrumb(pluginConfig, collection, breadcrumbDocs.slice(0, i + 1)),
) // eslint-disable-line function-paren-newline
return {
...newData,
[pluginConfig?.breadcrumbsFieldSlug || 'breadcrumbs']: breadcrumbs,
}
}
export default populateBreadcrumbs

View File

@@ -1,25 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": true, // Make sure typescript knows that this module depends on their references
"noEmit": false /* Do not emit outputs. */,
"emitDeclarationOnly": true,
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
"jsx": "react"
},
"exclude": [
"dist",
"build",
"tests",
"test",
"node_modules",
".eslintrc.js",
"src/**/*.spec.js",
"src/**/*.spec.jsx",
"src/**/*.spec.ts",
"src/**/*.spec.tsx"
],
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"],
"references": [{ "path": "../payload" }] // db-mongodb depends on payload
}

Some files were not shown because too many files have changed in this diff Show More