Compare commits
116 Commits
db-postgre
...
db-postgre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
084e9f0ff8 | ||
|
|
9f0ef9b7da | ||
|
|
c384f490c8 | ||
|
|
45a62ba949 | ||
|
|
1eae5f9c99 | ||
|
|
dfa861557d | ||
|
|
228fd58020 | ||
|
|
150799e10e | ||
|
|
823436a883 | ||
|
|
cbb0ba1a2c | ||
|
|
cb39354a9d | ||
|
|
1625ff244e | ||
|
|
24918fe1d2 | ||
|
|
b8a58666e7 | ||
|
|
2e6a2c8355 | ||
|
|
1fdff92525 | ||
|
|
7da5f6e92a | ||
|
|
67c7572e5f | ||
|
|
e311e8fff9 | ||
|
|
086e50b9b3 | ||
|
|
66ab6c587d | ||
|
|
786fb926c2 | ||
|
|
7d954b11a3 | ||
|
|
3c5044368d | ||
|
|
f129d6c607 | ||
|
|
de2d985405 | ||
|
|
060f3c73fa | ||
|
|
62ae7be113 | ||
|
|
771df061b4 | ||
|
|
09e64c3be8 | ||
|
|
1a006fef19 | ||
|
|
c4cac99875 | ||
|
|
d616772740 | ||
|
|
4b9e87bb4d | ||
|
|
ff5e174497 | ||
|
|
34017e1758 | ||
|
|
23d95526ab | ||
|
|
59b87fdb21 | ||
|
|
f2ac1f7d48 | ||
|
|
8d4f39af5e | ||
|
|
c4ac341d75 | ||
|
|
3eefe8cb21 | ||
|
|
8938f2b7e9 | ||
|
|
ed8a9ffa09 | ||
|
|
b5b487ab90 | ||
|
|
940bfe4f18 | ||
|
|
41dcdd4e01 | ||
|
|
3dbb70a9e6 | ||
|
|
adef360275 | ||
|
|
abebd7f440 | ||
|
|
e9ed969ad9 | ||
|
|
6b1a7f0843 | ||
|
|
e76cd58425 | ||
|
|
888f937e3c | ||
|
|
d61ced9cbd | ||
|
|
ada165a21e | ||
|
|
8d4fd14ff2 | ||
|
|
0363c85dbd | ||
|
|
fa660cd4ef | ||
|
|
4f6eb1e307 | ||
|
|
50860bc8c1 | ||
|
|
52f7890989 | ||
|
|
6200a119f9 | ||
|
|
46eb61d18a | ||
|
|
2766489476 | ||
|
|
0c1102a138 | ||
|
|
e765b96a4e | ||
|
|
01c42d9630 | ||
|
|
f421a2715d | ||
|
|
edd7a8086c | ||
|
|
010db46e08 | ||
|
|
fc8a6e107e | ||
|
|
2cb79f1752 | ||
|
|
5f740a60cc | ||
|
|
27313995cc | ||
|
|
93afe1d000 | ||
|
|
e7ffa2638a | ||
|
|
666765f3fb | ||
|
|
fc14622555 | ||
|
|
0d83d83d3c | ||
|
|
aab2f5f7d2 | ||
|
|
fbdc74ea71 | ||
|
|
141e40ffb9 | ||
|
|
bd2c1c6bf2 | ||
|
|
ba90fdbdfd | ||
|
|
9991fdb8c8 | ||
|
|
15c9ce56c2 | ||
|
|
eecdd0e118 | ||
|
|
f749732a0a | ||
|
|
78e2b518cf | ||
|
|
91362587f0 | ||
|
|
a4c4fc7060 | ||
|
|
db09f4839f | ||
|
|
c71e079fae | ||
|
|
b90785fa8c | ||
|
|
6e340f008f | ||
|
|
e08e681eda | ||
|
|
238db1750c | ||
|
|
0962cd6fcb | ||
|
|
6b436d38e1 | ||
|
|
ae93006446 | ||
|
|
fc722573bf | ||
|
|
b72ba7fe86 | ||
|
|
3dd777343b | ||
|
|
f1f7592eb2 | ||
|
|
3816589e8b | ||
|
|
ba70b8065e | ||
|
|
9b88a47a47 | ||
|
|
9a747bc1eb | ||
|
|
f82723ef33 | ||
|
|
897f7be0f7 | ||
|
|
80f6c7ebe1 | ||
|
|
9da4151642 | ||
|
|
b89cbe5715 | ||
|
|
725a1d35ef | ||
|
|
2fbfb5d305 |
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@@ -213,8 +213,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
pkg:
|
pkg:
|
||||||
- plugin-cloud
|
|
||||||
- create-payload-app
|
- create-payload-app
|
||||||
|
- plugin-cloud
|
||||||
|
- plugin-nested-docs
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Use Node.js 18
|
- name: Use Node.js 18
|
||||||
|
|||||||
83
CHANGELOG.md
83
CHANGELOG.md
@@ -1,3 +1,86 @@
|
|||||||
|
## [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)
|
## [2.0.0](https://github.com/payloadcms/payload/releases/tag/v2.0.0) (2023-10-09)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -496,6 +496,16 @@
|
|||||||
"@jridgewell/trace-mapping" "^0.3.17"
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
jsesc "^2.5.1"
|
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":
|
"@babel/helper-compilation-targets@^7.22.15":
|
||||||
version "7.22.15"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52"
|
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz#0698fc44551a26cf29f18d4662d5bf545a6cfc52"
|
||||||
@@ -507,18 +517,23 @@
|
|||||||
lru-cache "^5.1.1"
|
lru-cache "^5.1.1"
|
||||||
semver "^6.3.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":
|
"@babel/helper-environment-visitor@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
|
||||||
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
|
integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
|
||||||
|
|
||||||
"@babel/helper-function-name@^7.22.5":
|
"@babel/helper-function-name@^7.23.0":
|
||||||
version "7.22.5"
|
version "7.23.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
|
||||||
integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
|
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/template" "^7.22.5"
|
"@babel/template" "^7.22.15"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.23.0"
|
||||||
|
|
||||||
"@babel/helper-hoist-variables@^7.22.5":
|
"@babel/helper-hoist-variables@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
@@ -574,6 +589,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz#601fa28e4cc06786c18912dca138cec73b882044"
|
||||||
integrity sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==
|
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":
|
"@babel/helper-validator-option@^7.22.15":
|
||||||
version "7.22.15"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
|
||||||
@@ -602,6 +622,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.16.tgz#180aead7f247305cce6551bea2720934e2fa2c95"
|
||||||
integrity sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==
|
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":
|
"@babel/plugin-syntax-async-generators@^7.8.4":
|
||||||
version "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"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
|
||||||
@@ -707,7 +732,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.14.0"
|
regenerator-runtime "^0.14.0"
|
||||||
|
|
||||||
"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3":
|
"@babel/template@^7.22.15", "@babel/template@^7.3.3":
|
||||||
version "7.22.15"
|
version "7.22.15"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
||||||
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
||||||
@@ -717,18 +742,18 @@
|
|||||||
"@babel/types" "^7.22.15"
|
"@babel/types" "^7.22.15"
|
||||||
|
|
||||||
"@babel/traverse@^7.22.15", "@babel/traverse@^7.22.17":
|
"@babel/traverse@^7.22.15", "@babel/traverse@^7.22.17":
|
||||||
version "7.22.17"
|
version "7.23.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.17.tgz#b23c203ab3707e3be816043081b4a994fcacec44"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
||||||
integrity sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==
|
integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.22.13"
|
"@babel/code-frame" "^7.22.13"
|
||||||
"@babel/generator" "^7.22.15"
|
"@babel/generator" "^7.23.0"
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
"@babel/helper-environment-visitor" "^7.22.20"
|
||||||
"@babel/helper-function-name" "^7.22.5"
|
"@babel/helper-function-name" "^7.23.0"
|
||||||
"@babel/helper-hoist-variables" "^7.22.5"
|
"@babel/helper-hoist-variables" "^7.22.5"
|
||||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||||
"@babel/parser" "^7.22.16"
|
"@babel/parser" "^7.23.0"
|
||||||
"@babel/types" "^7.22.17"
|
"@babel/types" "^7.23.0"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
|
||||||
@@ -741,6 +766,15 @@
|
|||||||
"@babel/helper-validator-identifier" "^7.22.15"
|
"@babel/helper-validator-identifier" "^7.22.15"
|
||||||
to-fast-properties "^2.0.0"
|
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":
|
"@bcherny/json-schema-ref-parser@9.0.9":
|
||||||
version "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"
|
resolved "https://registry.yarnpkg.com/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#09899d405bc708c0acac0066ae8db5b94d465ca4"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"@types/prompts": "^2.4.5",
|
"@types/prompts": "^2.4.5",
|
||||||
"@types/qs": "6.9.7",
|
"@types/qs": "6.9.7",
|
||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
|
"@types/semver": "^7.5.3",
|
||||||
"@types/shelljs": "0.8.12",
|
"@types/shelljs": "0.8.12",
|
||||||
"@types/testing-library__jest-dom": "5.14.8",
|
"@types/testing-library__jest-dom": "5.14.8",
|
||||||
"chalk": "^5.3.0",
|
"chalk": "^5.3.0",
|
||||||
@@ -59,6 +60,7 @@
|
|||||||
"fs-extra": "10.1.0",
|
"fs-extra": "10.1.0",
|
||||||
"get-port": "5.1.1",
|
"get-port": "5.1.1",
|
||||||
"glob": "8.1.0",
|
"glob": "8.1.0",
|
||||||
|
"graphql-request": "6.1.0",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"isomorphic-fetch": "3.0.0",
|
"isomorphic-fetch": "3.0.0",
|
||||||
"jest": "29.6.4",
|
"jest": "29.6.4",
|
||||||
@@ -73,6 +75,7 @@
|
|||||||
"prompts": "2.4.2",
|
"prompts": "2.4.2",
|
||||||
"qs": "6.11.2",
|
"qs": "6.11.2",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
|
"semver": "^7.5.4",
|
||||||
"shelljs": "0.8.5",
|
"shelljs": "0.8.5",
|
||||||
"simple-git": "^3.20.0",
|
"simple-git": "^3.20.0",
|
||||||
"slash": "3.0.0",
|
"slash": "3.0.0",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { BundlerType, CliArgs, DbType, ProjectTemplate } from '../types'
|
|||||||
import { createProject } from './create-project'
|
import { createProject } from './create-project'
|
||||||
import { bundlerPackages, dbPackages, editorPackages } from './packages'
|
import { bundlerPackages, dbPackages, editorPackages } from './packages'
|
||||||
import exp from 'constants'
|
import exp from 'constants'
|
||||||
|
import { getValidTemplates } from './templates'
|
||||||
|
|
||||||
const projectDir = path.resolve(__dirname, './tmp')
|
const projectDir = path.resolve(__dirname, './tmp')
|
||||||
describe('createProject', () => {
|
describe('createProject', () => {
|
||||||
@@ -78,17 +79,20 @@ describe('createProject', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('db adapters and bundlers', () => {
|
describe('db adapters and bundlers', () => {
|
||||||
|
const templates = getValidTemplates()
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
['mongodb', 'webpack'],
|
['blank', 'mongodb', 'webpack'],
|
||||||
['postgres', 'webpack'],
|
['blank', 'postgres', 'webpack'],
|
||||||
])('update config and deps: %s, %s', async (db, bundler) => {
|
['website', 'mongodb', 'webpack'],
|
||||||
|
['website', 'postgres', 'webpack'],
|
||||||
|
['ecommerce', 'mongodb', 'webpack'],
|
||||||
|
['ecommerce', 'postgres', 'webpack'],
|
||||||
|
])('update config and deps: %s, %s, %s', async (templateName, db, bundler) => {
|
||||||
const projectName = 'starter-project'
|
const projectName = 'starter-project'
|
||||||
const template: ProjectTemplate = {
|
|
||||||
name: 'blank',
|
const template = templates.find((t) => t.name === templateName)
|
||||||
type: 'starter',
|
|
||||||
url: 'https://github.com/payloadcms/payload/templates/blank',
|
|
||||||
description: 'Blank Template',
|
|
||||||
}
|
|
||||||
await createProject({
|
await createProject({
|
||||||
cliArgs: args,
|
cliArgs: args,
|
||||||
projectName,
|
projectName,
|
||||||
@@ -124,7 +128,12 @@ describe('createProject', () => {
|
|||||||
editorReplacement.version,
|
editorReplacement.version,
|
||||||
)
|
)
|
||||||
|
|
||||||
const payloadConfigPath = path.resolve(projectDir, 'src/payload.config.ts')
|
let payloadConfigPath = path.resolve(projectDir, 'src/payload.config.ts')
|
||||||
|
|
||||||
|
// Website and ecommerce templates have payload.config.ts in src/payload
|
||||||
|
if (!fse.existsSync(payloadConfigPath)) {
|
||||||
|
payloadConfigPath = path.resolve(projectDir, 'src/payload/payload.config.ts')
|
||||||
|
}
|
||||||
const content = fse.readFileSync(payloadConfigPath, 'utf-8')
|
const content = fse.readFileSync(payloadConfigPath, 'utf-8')
|
||||||
|
|
||||||
// Check payload.config.ts
|
// Check payload.config.ts
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/db-postgres",
|
"name": "@payloadcms/db-postgres",
|
||||||
"version": "0.1.7",
|
"version": "0.1.9",
|
||||||
"description": "The officially supported Postgres database adapter for Payload",
|
"description": "The officially supported Postgres database adapter for Payload",
|
||||||
"repository": "https://github.com/payloadcms/payload",
|
"repository": "https://github.com/payloadcms/payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const findMany = async function find({
|
|||||||
const db = adapter.sessions[req.transactionID]?.db || adapter.drizzle
|
const db = adapter.sessions[req.transactionID]?.db || adapter.drizzle
|
||||||
const table = adapter.tables[tableName]
|
const table = adapter.tables[tableName]
|
||||||
|
|
||||||
let limit = limitArg
|
let limit = limitArg ?? 10
|
||||||
let totalDocs: number
|
let totalDocs: number
|
||||||
let totalPages: number
|
let totalPages: number
|
||||||
let hasPrevPage: boolean
|
let hasPrevPage: boolean
|
||||||
@@ -119,7 +119,11 @@ export const findMany = async function find({
|
|||||||
findManyArgs.where = inArray(adapter.tables[tableName].id, Object.keys(orderedIDMap))
|
findManyArgs.where = inArray(adapter.tables[tableName].id, Object.keys(orderedIDMap))
|
||||||
} else {
|
} else {
|
||||||
findManyArgs.limit = limitArg === 0 ? undefined : limitArg
|
findManyArgs.limit = limitArg === 0 ? undefined : limitArg
|
||||||
findManyArgs.offset = skip || (page - 1) * limitArg
|
|
||||||
|
const offset = skip || (page - 1) * limitArg
|
||||||
|
|
||||||
|
if (!Number.isNaN(offset)) findManyArgs.offset = offset
|
||||||
|
|
||||||
if (where) {
|
if (where) {
|
||||||
findManyArgs.where = where
|
findManyArgs.where = where
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export const traverseFields = ({
|
|||||||
currentTableName,
|
currentTableName,
|
||||||
depth,
|
depth,
|
||||||
fields: block.fields,
|
fields: block.fields,
|
||||||
path,
|
path: '',
|
||||||
topLevelArgs,
|
topLevelArgs,
|
||||||
topLevelTableName,
|
topLevelTableName,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -148,13 +148,19 @@ export async function parseParams({
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const { operator: queryOperator, value: queryValue } = sanitizeQueryValue({
|
const sanitizedQueryValue = sanitizeQueryValue({
|
||||||
field,
|
field,
|
||||||
operator,
|
operator,
|
||||||
relationOrPath,
|
relationOrPath,
|
||||||
val,
|
val,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (sanitizedQueryValue === null) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
const { operator: queryOperator, value: queryValue } = sanitizedQueryValue
|
||||||
|
|
||||||
if (queryOperator === 'not_equals' && queryValue !== null) {
|
if (queryOperator === 'not_equals' && queryValue !== null) {
|
||||||
constraints.push(
|
constraints.push(
|
||||||
or(
|
or(
|
||||||
@@ -163,7 +169,10 @@ export async function parseParams({
|
|||||||
ne<any>(rawColumn || table[columnName], queryValue),
|
ne<any>(rawColumn || table[columnName], queryValue),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else if (
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
(field.type === 'relationship' || field.type === 'upload') &&
|
(field.type === 'relationship' || field.type === 'upload') &&
|
||||||
Array.isArray(queryValue) &&
|
Array.isArray(queryValue) &&
|
||||||
operator === 'not_in'
|
operator === 'not_in'
|
||||||
@@ -174,7 +183,10 @@ export async function parseParams({
|
|||||||
IS
|
IS
|
||||||
NULL`,
|
NULL`,
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
constraints.push(
|
constraints.push(
|
||||||
operatorMap[queryOperator](rawColumn || table[columnName], queryValue),
|
operatorMap[queryOperator](rawColumn || table[columnName], queryValue),
|
||||||
)
|
)
|
||||||
@@ -185,7 +197,6 @@ export async function parseParams({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (constraints.length > 0) {
|
if (constraints.length > 0) {
|
||||||
if (result) {
|
if (result) {
|
||||||
result = and(result, ...constraints)
|
result = and(result, ...constraints)
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ export const sanitizeQueryValue = ({
|
|||||||
if (val.toLowerCase() === 'false') formattedValue = false
|
if (val.toLowerCase() === 'false') formattedValue = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['all', 'in', 'not_in'].includes(operator) && typeof formattedValue === 'string') {
|
if (['all', 'in', 'not_in'].includes(operator)) {
|
||||||
|
if (typeof formattedValue === 'string') {
|
||||||
formattedValue = createArrayFromCommaDelineated(formattedValue)
|
formattedValue = createArrayFromCommaDelineated(formattedValue)
|
||||||
|
|
||||||
if (field.type === 'number') {
|
if (field.type === 'number') {
|
||||||
@@ -50,6 +51,11 @@ export const sanitizeQueryValue = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(formattedValue) || formattedValue.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (field.type === 'number' && typeof formattedValue === 'string') {
|
if (field.type === 'number' && typeof formattedValue === 'string') {
|
||||||
formattedValue = Number(val)
|
formattedValue = Number(val)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "payload",
|
"name": "payload",
|
||||||
"version": "2.0.6",
|
"version": "2.0.7",
|
||||||
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
@@ -187,7 +187,6 @@
|
|||||||
"file-loader": "6.2.0",
|
"file-loader": "6.2.0",
|
||||||
"form-data": "3.0.1",
|
"form-data": "3.0.1",
|
||||||
"get-port": "5.1.1",
|
"get-port": "5.1.1",
|
||||||
"graphql-request": "6.1.0",
|
|
||||||
"mini-css-extract-plugin": "1.6.2",
|
"mini-css-extract-plugin": "1.6.2",
|
||||||
"node-fetch": "2.6.12",
|
"node-fetch": "2.6.12",
|
||||||
"nodemon": "3.0.1",
|
"nodemon": "3.0.1",
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { toast } from 'react-toastify'
|
|||||||
import type { Props } from './types'
|
import type { Props } from './types'
|
||||||
|
|
||||||
import useDebounce from '../../../hooks/useDebounce'
|
import useDebounce from '../../../hooks/useDebounce'
|
||||||
|
import { formatTimeToNow } from '../../../utilities/formatDate'
|
||||||
import { useAllFormFields, useFormModified } from '../../forms/Form/context'
|
import { useAllFormFields, useFormModified } from '../../forms/Form/context'
|
||||||
import reduceFieldsToValues from '../../forms/Form/reduceFieldsToValues'
|
import reduceFieldsToValues from '../../forms/Form/reduceFieldsToValues'
|
||||||
import { useConfig } from '../../utilities/Config'
|
import { useConfig } from '../../utilities/Config'
|
||||||
import { useDocumentInfo } from '../../utilities/DocumentInfo'
|
import { useDocumentInfo } from '../../utilities/DocumentInfo'
|
||||||
import { useLocale } from '../../utilities/Locale'
|
import { useLocale } from '../../utilities/Locale'
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
const baseClass = 'autosave'
|
const baseClass = 'autosave'
|
||||||
|
|
||||||
const Autosave: React.FC<Props> = ({ id, collection, global, publishedDocUpdatedAt }) => {
|
const Autosave: React.FC<Props> = ({ id, collection, global, publishedDocUpdatedAt }) => {
|
||||||
@@ -163,7 +163,7 @@ const Autosave: React.FC<Props> = ({ id, collection, global, publishedDocUpdated
|
|||||||
{!saving && lastSaved && (
|
{!saving && lastSaved && (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{t('lastSavedAgo', {
|
{t('lastSavedAgo', {
|
||||||
distance: Math.round((Number(new Date(lastSaved)) - Number(new Date())) / 1000 / 60),
|
distance: formatTimeToNow(lastSaved, i18n.language),
|
||||||
})}
|
})}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -28,10 +28,10 @@
|
|||||||
gap: var(--base);
|
gap: var(--base);
|
||||||
padding-bottom: 1px;
|
padding-bottom: 1px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
height: var(--doc-controls-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
height: var(--doc-controls-height);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
@@ -140,21 +140,21 @@
|
|||||||
// On mobile, only stick the controls to the top
|
// On mobile, only stick the controls to the top
|
||||||
// The timestamps and meta can scroll past
|
// The timestamps and meta can scroll past
|
||||||
// The same container needs to the sticky, though
|
// The same container needs to the sticky, though
|
||||||
// So we use a static height with a negative top
|
// So we use a static height with a negative top equal to the meta height plus top padding
|
||||||
top: calc(var(--doc-controls-height) * -1);
|
top: calc(var(--base) * -2);
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|
||||||
&__wrapper {
|
&__wrapper {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
|
height: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content {
|
&__content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
align-items: flex-start;
|
|
||||||
padding-top: calc(var(--base) / 2);
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
height: calc(var(--base) * 2);
|
||||||
|
|
||||||
// this container has a fixed height
|
// this container has a fixed height
|
||||||
// this means the scrollbar (when present) overlaps the content
|
// this means the scrollbar (when present) overlaps the content
|
||||||
@@ -167,26 +167,52 @@
|
|||||||
width: auto;
|
width: auto;
|
||||||
gap: calc(var(--base) / 2);
|
gap: calc(var(--base) / 2);
|
||||||
margin-left: var(--gutter-h);
|
margin-left: var(--gutter-h);
|
||||||
margin-right: 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__controls-wrapper {
|
&__controls-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transform: translate3d(0, 0, 0);
|
transform: translate3d(0, 0, 0);
|
||||||
padding: calc(var(--base) / 2) 0;
|
padding-right: var(--gutter-h);
|
||||||
overflow: auto;
|
justify-content: space-between;
|
||||||
|
height: var(--doc-controls-height);
|
||||||
|
border-top: 1px solid var(--theme-elevation-100);
|
||||||
}
|
}
|
||||||
|
|
||||||
&__controls {
|
&__controls {
|
||||||
margin-left: var(--gutter-h);
|
padding-left: var(--gutter-h);
|
||||||
margin-right: var(--gutter-h);
|
overflow: auto;
|
||||||
|
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__popup {
|
&::after {
|
||||||
// TODO: the container needs to overflow on mobile
|
content: '';
|
||||||
// But the popup interferes with this because it requires overflow in order to be visible
|
display: block;
|
||||||
// So we likely need to outright show the controls nested within the popup on mobile
|
position: sticky;
|
||||||
display: none;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import React, { Fragment } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import type { CollectionPermission, GlobalPermission } from '../../../../auth'
|
import type { CollectionPermission, GlobalPermission } from '../../../../auth'
|
||||||
import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from '../../../../exports/types'
|
import type { SanitizedCollectionConfig } from '../../../../collections/config/types'
|
||||||
|
import type { SanitizedGlobalConfig } from '../../../../globals/config/types'
|
||||||
|
|
||||||
import { formatDate } from '../../../utilities/formatDate'
|
import { formatDate } from '../../../utilities/formatDate'
|
||||||
import { useConfig } from '../../utilities/Config'
|
import { useConfig } from '../../utilities/Config'
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useModal } from '@faceless-ui/modal'
|
import { useModal } from '@faceless-ui/modal'
|
||||||
|
import queryString from 'qs'
|
||||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
@@ -16,6 +17,7 @@ import X from '../../icons/X'
|
|||||||
import { useAuth } from '../../utilities/Auth'
|
import { useAuth } from '../../utilities/Auth'
|
||||||
import { useConfig } from '../../utilities/Config'
|
import { useConfig } from '../../utilities/Config'
|
||||||
import { DocumentInfoProvider, useDocumentInfo } from '../../utilities/DocumentInfo'
|
import { DocumentInfoProvider, useDocumentInfo } from '../../utilities/DocumentInfo'
|
||||||
|
import { useFormQueryParams } from '../../utilities/FormQueryParams'
|
||||||
import { useLocale } from '../../utilities/Locale'
|
import { useLocale } from '../../utilities/Locale'
|
||||||
import RenderCustomComponent from '../../utilities/RenderCustomComponent'
|
import RenderCustomComponent from '../../utilities/RenderCustomComponent'
|
||||||
import DefaultEdit from '../../views/collections/Edit/Default'
|
import DefaultEdit from '../../views/collections/Edit/Default'
|
||||||
@@ -42,6 +44,8 @@ const Content: React.FC<DocumentDrawerProps> = ({
|
|||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const [collectionConfig] = useRelatedCollections(collectionSlug)
|
const [collectionConfig] = useRelatedCollections(collectionSlug)
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
|
const { formQueryParams } = useFormQueryParams()
|
||||||
|
const formattedQueryParams = queryString.stringify(formQueryParams)
|
||||||
|
|
||||||
const { admin: { components: { views: { Edit } = {} } = {} } = {} } = collectionConfig
|
const { admin: { components: { views: { Edit } = {} } = {} } = {} } = collectionConfig
|
||||||
|
|
||||||
@@ -117,8 +121,8 @@ const Content: React.FC<DocumentDrawerProps> = ({
|
|||||||
const apiURL = id ? `${serverURL}${api}/${collectionSlug}/${id}?locale=${locale}` : null
|
const apiURL = id ? `${serverURL}${api}/${collectionSlug}/${id}?locale=${locale}` : null
|
||||||
|
|
||||||
const action = `${serverURL}${api}/${collectionSlug}${
|
const action = `${serverURL}${api}/${collectionSlug}${
|
||||||
id ? `/${id}` : ''
|
isEditing ? `/${id}` : ''
|
||||||
}?locale=${locale}&fallback-locale=null`
|
}?${formattedQueryParams}`
|
||||||
|
|
||||||
const hasSavePermission =
|
const hasSavePermission =
|
||||||
(isEditing && docPermissions?.update?.permission) ||
|
(isEditing && docPermissions?.update?.permission) ||
|
||||||
|
|||||||
@@ -17,6 +17,24 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: auto;
|
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 {
|
&__tabs {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-left: var(--gutter-h);
|
margin-left: var(--gutter-h);
|
||||||
|
|||||||
@@ -35,11 +35,6 @@ $header-height: base(5);
|
|||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cancel,
|
|
||||||
&__save {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__toolWrap {
|
&__toolWrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|||||||
@@ -50,14 +50,13 @@ export const EditUpload: React.FC<{
|
|||||||
y: uploadEdits?.focalPoint?.y || 50,
|
y: uploadEdits?.focalPoint?.y || 50,
|
||||||
})
|
})
|
||||||
const [checkBounds, setCheckBounds] = useState<boolean>(false)
|
const [checkBounds, setCheckBounds] = useState<boolean>(false)
|
||||||
|
const [originalHeight, setOriginalHeight] = useState<number>(0)
|
||||||
|
const [originalWidth, setOriginalWidth] = useState<number>(0)
|
||||||
|
|
||||||
const focalWrapRef = useRef<HTMLDivElement | undefined>()
|
const focalWrapRef = useRef<HTMLDivElement | undefined>()
|
||||||
const imageRef = useRef<HTMLImageElement | undefined>()
|
const imageRef = useRef<HTMLImageElement | undefined>()
|
||||||
const cropRef = useRef<HTMLDivElement | 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 fineTuneCrop = ({ dimension, value }: { dimension: 'height' | 'width'; value: string }) => {
|
||||||
const intValue = parseInt(value)
|
const intValue = parseInt(value)
|
||||||
if (dimension === 'width' && intValue >= originalWidth) return null
|
if (dimension === 'width' && intValue >= originalWidth) return null
|
||||||
@@ -152,7 +151,15 @@ export const EditUpload: React.FC<{
|
|||||||
return <div className={`${baseClass}__crop-window`} ref={cropRef} />
|
return <div className={`${baseClass}__crop-window`} ref={cropRef} />
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img alt={t('upload:setCropArea')} ref={imageRef} src={fileSrcToUse} />
|
<img
|
||||||
|
alt={t('upload:setCropArea')}
|
||||||
|
onLoad={(e) => {
|
||||||
|
setOriginalHeight(e.currentTarget.naturalHeight)
|
||||||
|
setOriginalWidth(e.currentTarget.naturalWidth)
|
||||||
|
}}
|
||||||
|
ref={imageRef}
|
||||||
|
src={fileSrcToUse}
|
||||||
|
/>
|
||||||
</ReactCrop>
|
</ReactCrop>
|
||||||
) : (
|
) : (
|
||||||
<img alt={t('upload:setFocalPoint')} ref={imageRef} src={fileSrcToUse} />
|
<img alt={t('upload:setFocalPoint')} ref={imageRef} src={fileSrcToUse} />
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__preview {
|
&__preview {
|
||||||
max-height: calc(100% - base(4));
|
max-height: calc(100% - base(6));
|
||||||
padding: base(1.5) base(1.5) base(1.5) var(--gutter-h);
|
padding: base(1.5) base(1.5) base(1.5) var(--gutter-h);
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ const PreviewSizes: React.FC<{
|
|||||||
doc?: Data & {
|
doc?: Data & {
|
||||||
sizes?: FileSizes
|
sizes?: FileSizes
|
||||||
}
|
}
|
||||||
updatedAt?: string
|
imageCacheTag?: string
|
||||||
}> = ({ collection, doc, updatedAt }) => {
|
}> = ({ collection, doc, imageCacheTag }) => {
|
||||||
const {
|
const {
|
||||||
upload: { imageSizes, staticURL },
|
upload: { imageSizes, staticURL },
|
||||||
} = collection
|
} = collection
|
||||||
@@ -39,20 +39,15 @@ const PreviewSizes: React.FC<{
|
|||||||
const [selectedSize, setSelectedSize] = useState<null | string>(
|
const [selectedSize, setSelectedSize] = useState<null | string>(
|
||||||
orderedSizes?.[imageSizes[0]?.name]?.filename ? imageSizes[0]?.name : null,
|
orderedSizes?.[imageSizes[0]?.name]?.filename ? imageSizes[0]?.name : null,
|
||||||
)
|
)
|
||||||
const [appendUrl, setAppendUrl] = useState<boolean>(false)
|
|
||||||
|
|
||||||
const generateImageUrl = (filename) => {
|
const generateImageUrl = (filename) => {
|
||||||
const query = appendUrl ? `?${Date.now()}` : ''
|
return `${staticURL}/${filename}${imageCacheTag ? `?${imageCacheTag}` : ''}`
|
||||||
return `${staticURL}/${filename}${query}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setOrderedSizes(sortSizes(sizes, imageSizes))
|
setOrderedSizes(sortSizes(sizes, imageSizes))
|
||||||
}, [sizes, imageSizes, updatedAt])
|
}, [sizes, imageSizes, imageCacheTag])
|
||||||
|
|
||||||
useEffect(() => {
|
const mainPreviewSrc = generateImageUrl(`${orderedSizes[selectedSize]?.filename}`)
|
||||||
setAppendUrl(true)
|
|
||||||
}, [updatedAt])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={baseClass}>
|
<div className={baseClass}>
|
||||||
@@ -61,17 +56,15 @@ const PreviewSizes: React.FC<{
|
|||||||
<div className={`${baseClass}__sizeName`}>{selectedSize}</div>
|
<div className={`${baseClass}__sizeName`}>{selectedSize}</div>
|
||||||
<Meta {...(selectedSize && orderedSizes[selectedSize])} staticURL={staticURL} />
|
<Meta {...(selectedSize && orderedSizes[selectedSize])} staticURL={staticURL} />
|
||||||
</div>
|
</div>
|
||||||
<img
|
<img alt={doc.filename} className={`${baseClass}__preview`} src={mainPreviewSrc} />
|
||||||
alt={doc.filename}
|
|
||||||
className={`${baseClass}__preview`}
|
|
||||||
src={generateImageUrl(`${orderedSizes[selectedSize]?.filename}`)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className={`${baseClass}__listWrap`}>
|
<div className={`${baseClass}__listWrap`}>
|
||||||
<div className={`${baseClass}__list`}>
|
<div className={`${baseClass}__list`}>
|
||||||
{Object.entries(orderedSizes).map(([key, val]) => {
|
{Object.entries(orderedSizes).map(([key, val]) => {
|
||||||
const selected = selectedSize === key
|
const selected = selectedSize === key
|
||||||
if (val?.filename) {
|
const previewSrc = generateImageUrl(val.filename)
|
||||||
|
|
||||||
|
if (previewSrc) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={[`${baseClass}__sizeOption`, selected && `${baseClass}--selected`]
|
className={[`${baseClass}__sizeOption`, selected && `${baseClass}--selected`]
|
||||||
@@ -88,7 +81,7 @@ const PreviewSizes: React.FC<{
|
|||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<div className={`${baseClass}__image`}>
|
<div className={`${baseClass}__image`}>
|
||||||
<img alt={val.filename} src={generateImageUrl(val.filename)} />
|
<img alt={val.filename} src={previewSrc} />
|
||||||
</div>
|
</div>
|
||||||
<div className={`${baseClass}__sizeMeta`}>
|
<div className={`${baseClass}__sizeMeta`}>
|
||||||
<div className={`${baseClass}__sizeName`}>{key}</div>
|
<div className={`${baseClass}__sizeName`}>{key}</div>
|
||||||
|
|||||||
@@ -25,12 +25,9 @@ const Thumbnail: React.FC<Props> = (props) => {
|
|||||||
const classes = [baseClass, `${baseClass}--size-${size || 'medium'}`, className].join(' ')
|
const classes = [baseClass, `${baseClass}--size-${size || 'medium'}`, className].join(' ')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (doc && collection && thumbnailSRC) {
|
if (thumbnailSRC) {
|
||||||
setSrc(`${thumbnailSRC}${imageCacheTag ? `?${imageCacheTag}` : ''}`)
|
setSrc(`${thumbnailSRC}${imageCacheTag ? `?${imageCacheTag}` : ''}`)
|
||||||
}
|
}
|
||||||
if (fileSrc) {
|
|
||||||
setSrc(fileSrc)
|
|
||||||
}
|
|
||||||
}, [doc, collection, thumbnailSRC, fileSrc, imageCacheTag])
|
}, [doc, collection, thumbnailSRC, fileSrc, imageCacheTag])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ const BlocksField: React.FC<Props> = (props) => {
|
|||||||
</DrawerToggler>
|
</DrawerToggler>
|
||||||
<BlocksDrawer
|
<BlocksDrawer
|
||||||
addRow={addRow}
|
addRow={addRow}
|
||||||
addRowIndex={value || 0}
|
addRowIndex={rows?.length || 0}
|
||||||
blocks={blocks}
|
blocks={blocks}
|
||||||
drawerSlug={drawerSlug}
|
drawerSlug={drawerSlug}
|
||||||
labels={labels}
|
labels={labels}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ export const DefaultCollectionEdit: React.FC<CollectionEditViewProps> = (props)
|
|||||||
internalState,
|
internalState,
|
||||||
isEditing,
|
isEditing,
|
||||||
permissions,
|
permissions,
|
||||||
updatedAt,
|
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const { auth, fields, upload } = collection
|
const { auth, fields, upload } = collection
|
||||||
@@ -97,9 +96,7 @@ export const DefaultCollectionEdit: React.FC<CollectionEditViewProps> = (props)
|
|||||||
verify={auth.verify}
|
verify={auth.verify}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{upload && (
|
{upload && <Upload collection={collection} internalState={internalState} />}
|
||||||
<Upload collection={collection} internalState={internalState} updatedAt={updatedAt} />
|
|
||||||
)}
|
|
||||||
<RenderFields
|
<RenderFields
|
||||||
className={`${baseClass}__fields`}
|
className={`${baseClass}__fields`}
|
||||||
fieldSchema={fields}
|
fieldSchema={fields}
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ export const Upload: React.FC<Props> = (props) => {
|
|||||||
slug={sizePreviewSlug}
|
slug={sizePreviewSlug}
|
||||||
title={t('upload:sizesFor', { label: doc?.filename })}
|
title={t('upload:sizesFor', { label: doc?.filename })}
|
||||||
>
|
>
|
||||||
<PreviewSizes collection={collection} doc={doc} updatedAt={updatedAt} />
|
<PreviewSizes collection={collection} doc={doc} />
|
||||||
</Drawer>
|
</Drawer>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
@include mid-break {
|
@include mid-break {
|
||||||
--gutter-h: #{base(2)};
|
--gutter-h: #{base(2)};
|
||||||
--app-header-height: calc(var(--base) * 2);
|
--app-header-height: calc(var(--base) * 2);
|
||||||
--doc-controls-height: calc(var(--base) * 1.5);
|
--doc-controls-height: calc(var(--base) * 2.5);
|
||||||
// set to xs-breakpoint to achieve a seamless transition to full screen
|
// set to xs-breakpoint to achieve a seamless transition to full screen
|
||||||
--nav-width: var(--breakpoint-xs-width);
|
--nav-width: var(--breakpoint-xs-width);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { format } from 'date-fns'
|
import { format, formatDistanceToNow } from 'date-fns'
|
||||||
import * as Locale from 'date-fns/locale'
|
import * as Locale from 'date-fns/locale'
|
||||||
|
|
||||||
import { getSupportedDateLocale } from './getSupportedDateLocale'
|
import { getSupportedDateLocale } from './getSupportedDateLocale'
|
||||||
@@ -12,3 +12,12 @@ export const formatDate = (
|
|||||||
const currentLocale = Locale[getSupportedDateLocale(locale)]
|
const currentLocale = Locale[getSupportedDateLocale(locale)]
|
||||||
return format(theDate, pattern, { locale: currentLocale })
|
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 })
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ import type { PayloadRequest } from '../../../express/types'
|
|||||||
import type { Payload } from '../../../payload'
|
import type { Payload } from '../../../payload'
|
||||||
|
|
||||||
import { APIError } from '../../../errors'
|
import { APIError } from '../../../errors'
|
||||||
|
import { setRequestContext } from '../../../express/setRequestContext'
|
||||||
|
import { i18nInit } from '../../../translations/init'
|
||||||
import verifyEmail from '../verifyEmail'
|
import verifyEmail from '../verifyEmail'
|
||||||
|
|
||||||
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
export type Options<T extends keyof GeneratedTypes['collections']> = {
|
||||||
collection: T
|
collection: T
|
||||||
|
req?: PayloadRequest
|
||||||
token: string
|
token: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,11 +17,8 @@ async function localVerifyEmail<T extends keyof GeneratedTypes['collections']>(
|
|||||||
payload: Payload,
|
payload: Payload,
|
||||||
options: Options<T>,
|
options: Options<T>,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const { collection: collectionSlug, token } = options
|
const { collection: collectionSlug, req = {} as PayloadRequest, token } = options
|
||||||
|
setRequestContext(options.req)
|
||||||
const req = {
|
|
||||||
payload,
|
|
||||||
} as PayloadRequest
|
|
||||||
|
|
||||||
const collection = payload.collections[collectionSlug]
|
const collection = payload.collections[collectionSlug]
|
||||||
|
|
||||||
@@ -28,6 +28,10 @@ async function localVerifyEmail<T extends keyof GeneratedTypes['collections']>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req.payload = payload
|
||||||
|
req.payloadAPI = req.payloadAPI || 'local'
|
||||||
|
req.i18n = i18nInit(payload.config.i18n)
|
||||||
|
|
||||||
return verifyEmail({
|
return verifyEmail({
|
||||||
collection,
|
collection,
|
||||||
req,
|
req,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
|
|||||||
locale?: string
|
locale?: string
|
||||||
overrideAccess?: boolean
|
overrideAccess?: boolean
|
||||||
page?: number
|
page?: number
|
||||||
|
req?: PayloadRequest
|
||||||
showHiddenFields?: boolean
|
showHiddenFields?: boolean
|
||||||
sort?: string
|
sort?: string
|
||||||
user?: Document
|
user?: Document
|
||||||
@@ -43,6 +44,7 @@ export default async function findVersionsLocal<T extends keyof GeneratedTypes['
|
|||||||
locale = null,
|
locale = null,
|
||||||
overrideAccess = true,
|
overrideAccess = true,
|
||||||
page,
|
page,
|
||||||
|
req: incomingReq,
|
||||||
showHiddenFields,
|
showHiddenFields,
|
||||||
sort,
|
sort,
|
||||||
user,
|
user,
|
||||||
@@ -67,6 +69,7 @@ export default async function findVersionsLocal<T extends keyof GeneratedTypes['
|
|||||||
locale: locale ?? defaultLocale,
|
locale: locale ?? defaultLocale,
|
||||||
payload,
|
payload,
|
||||||
payloadAPI: 'local',
|
payloadAPI: 'local',
|
||||||
|
transactionID: incomingReq?.transactionID,
|
||||||
user,
|
user,
|
||||||
} as PayloadRequest
|
} as PayloadRequest
|
||||||
setRequestContext(req, context)
|
setRequestContext(req, context)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
|
|||||||
id: string
|
id: string
|
||||||
locale?: string
|
locale?: string
|
||||||
overrideAccess?: boolean
|
overrideAccess?: boolean
|
||||||
|
req?: PayloadRequest
|
||||||
showHiddenFields?: boolean
|
showHiddenFields?: boolean
|
||||||
user?: Document
|
user?: Document
|
||||||
}
|
}
|
||||||
@@ -37,6 +38,7 @@ export default async function restoreVersionLocal<T extends keyof GeneratedTypes
|
|||||||
fallbackLocale = null,
|
fallbackLocale = null,
|
||||||
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
||||||
overrideAccess = true,
|
overrideAccess = true,
|
||||||
|
req: incomingReq,
|
||||||
showHiddenFields,
|
showHiddenFields,
|
||||||
user,
|
user,
|
||||||
} = options
|
} = options
|
||||||
@@ -59,6 +61,7 @@ export default async function restoreVersionLocal<T extends keyof GeneratedTypes
|
|||||||
payload,
|
payload,
|
||||||
payloadAPI: 'local',
|
payloadAPI: 'local',
|
||||||
t: i18n.t,
|
t: i18n.t,
|
||||||
|
transactionID: incomingReq?.transactionID,
|
||||||
user,
|
user,
|
||||||
} as PayloadRequest
|
} as PayloadRequest
|
||||||
setRequestContext(req, context)
|
setRequestContext(req, context)
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ export type FilterOptionsProps<T = any> = {
|
|||||||
export type FilterOptions<T = any> =
|
export type FilterOptions<T = any> =
|
||||||
| ((options: FilterOptionsProps<T>) => Promise<Where> | Where)
|
| ((options: FilterOptionsProps<T>) => Promise<Where> | Where)
|
||||||
| Where
|
| Where
|
||||||
|
| null
|
||||||
|
|
||||||
type Admin = {
|
type Admin = {
|
||||||
className?: string
|
className?: string
|
||||||
|
|||||||
@@ -258,14 +258,18 @@ const validateFilterOptions: Validate = async (
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (valueIDs.length > 0) {
|
if (valueIDs.length > 0) {
|
||||||
|
const findWhere = {
|
||||||
|
and: [{ id: { in: valueIDs } }],
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optionFilter) findWhere.and.push(optionFilter)
|
||||||
|
|
||||||
const result = await payload.find({
|
const result = await payload.find({
|
||||||
collection,
|
collection,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
limit: 0,
|
limit: 0,
|
||||||
pagination: false,
|
pagination: false,
|
||||||
where: {
|
where: findWhere,
|
||||||
and: [{ id: { in: valueIDs } }, optionFilter],
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
options[collection] = result.docs.map((doc) => doc.id)
|
options[collection] = result.docs.map((doc) => doc.id)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export type Options<T extends keyof GeneratedTypes['globals']> = {
|
|||||||
id: string
|
id: string
|
||||||
locale?: string
|
locale?: string
|
||||||
overrideAccess?: boolean
|
overrideAccess?: boolean
|
||||||
|
req?: PayloadRequest
|
||||||
showHiddenFields?: boolean
|
showHiddenFields?: boolean
|
||||||
slug: T
|
slug: T
|
||||||
user?: Document
|
user?: Document
|
||||||
@@ -36,6 +37,7 @@ export default async function findVersionByIDLocal<T extends keyof GeneratedType
|
|||||||
showHiddenFields,
|
showHiddenFields,
|
||||||
slug: globalSlug,
|
slug: globalSlug,
|
||||||
user,
|
user,
|
||||||
|
req: incomingReq,
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
const globalConfig = payload.globals.config.find((config) => config.slug === globalSlug)
|
const globalConfig = payload.globals.config.find((config) => config.slug === globalSlug)
|
||||||
@@ -52,6 +54,7 @@ export default async function findVersionByIDLocal<T extends keyof GeneratedType
|
|||||||
payload,
|
payload,
|
||||||
payloadAPI: 'local',
|
payloadAPI: 'local',
|
||||||
t: i18n.t,
|
t: i18n.t,
|
||||||
|
transactionID: incomingReq?.transactionID,
|
||||||
user,
|
user,
|
||||||
} as PayloadRequest
|
} as PayloadRequest
|
||||||
setRequestContext(req)
|
setRequestContext(req)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export type Options<T extends keyof GeneratedTypes['globals']> = {
|
|||||||
locale?: string
|
locale?: string
|
||||||
overrideAccess?: boolean
|
overrideAccess?: boolean
|
||||||
page?: number
|
page?: number
|
||||||
|
req?: PayloadRequest
|
||||||
showHiddenFields?: boolean
|
showHiddenFields?: boolean
|
||||||
slug: T
|
slug: T
|
||||||
sort?: string
|
sort?: string
|
||||||
@@ -36,6 +37,7 @@ export default async function findVersionsLocal<T extends keyof GeneratedTypes['
|
|||||||
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
||||||
overrideAccess = true,
|
overrideAccess = true,
|
||||||
page,
|
page,
|
||||||
|
req: incomingReq,
|
||||||
showHiddenFields,
|
showHiddenFields,
|
||||||
slug: globalSlug,
|
slug: globalSlug,
|
||||||
sort,
|
sort,
|
||||||
@@ -57,6 +59,7 @@ export default async function findVersionsLocal<T extends keyof GeneratedTypes['
|
|||||||
payload,
|
payload,
|
||||||
payloadAPI: 'local',
|
payloadAPI: 'local',
|
||||||
t: i18n.t,
|
t: i18n.t,
|
||||||
|
transactionID: incomingReq?.transactionID,
|
||||||
user,
|
user,
|
||||||
} as PayloadRequest
|
} as PayloadRequest
|
||||||
setRequestContext(req)
|
setRequestContext(req)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export type Options<T extends keyof GeneratedTypes['globals']> = {
|
|||||||
id: string
|
id: string
|
||||||
locale?: string
|
locale?: string
|
||||||
overrideAccess?: boolean
|
overrideAccess?: boolean
|
||||||
|
req?: PayloadRequest
|
||||||
showHiddenFields?: boolean
|
showHiddenFields?: boolean
|
||||||
slug: string
|
slug: string
|
||||||
user?: Document
|
user?: Document
|
||||||
@@ -30,6 +31,7 @@ export default async function restoreVersionLocal<T extends keyof GeneratedTypes
|
|||||||
fallbackLocale = null,
|
fallbackLocale = null,
|
||||||
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
||||||
overrideAccess = true,
|
overrideAccess = true,
|
||||||
|
req: incomingReq,
|
||||||
showHiddenFields,
|
showHiddenFields,
|
||||||
slug: globalSlug,
|
slug: globalSlug,
|
||||||
user,
|
user,
|
||||||
@@ -49,6 +51,7 @@ export default async function restoreVersionLocal<T extends keyof GeneratedTypes
|
|||||||
payload,
|
payload,
|
||||||
payloadAPI: 'local',
|
payloadAPI: 'local',
|
||||||
t: i18n.t,
|
t: i18n.t,
|
||||||
|
transactionID: incomingReq?.transactionID,
|
||||||
user,
|
user,
|
||||||
} as PayloadRequest
|
} as PayloadRequest
|
||||||
setRequestContext(req)
|
setRequestContext(req)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export type Options<TSlug extends keyof GeneratedTypes['globals']> = {
|
|||||||
fallbackLocale?: string
|
fallbackLocale?: string
|
||||||
locale?: string
|
locale?: string
|
||||||
overrideAccess?: boolean
|
overrideAccess?: boolean
|
||||||
|
req?: PayloadRequest
|
||||||
showHiddenFields?: boolean
|
showHiddenFields?: boolean
|
||||||
slug: TSlug
|
slug: TSlug
|
||||||
user?: Document
|
user?: Document
|
||||||
@@ -34,6 +35,7 @@ export default async function updateLocal<TSlug extends keyof GeneratedTypes['gl
|
|||||||
fallbackLocale = null,
|
fallbackLocale = null,
|
||||||
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
locale = payload.config.localization ? payload.config.localization?.defaultLocale : null,
|
||||||
overrideAccess = true,
|
overrideAccess = true,
|
||||||
|
req: incomingReq,
|
||||||
showHiddenFields,
|
showHiddenFields,
|
||||||
slug: globalSlug,
|
slug: globalSlug,
|
||||||
user,
|
user,
|
||||||
@@ -53,6 +55,7 @@ export default async function updateLocal<TSlug extends keyof GeneratedTypes['gl
|
|||||||
payload,
|
payload,
|
||||||
payloadAPI: 'local',
|
payloadAPI: 'local',
|
||||||
t: i18n.t,
|
t: i18n.t,
|
||||||
|
transactionID: incomingReq?.transactionID,
|
||||||
user,
|
user,
|
||||||
} as PayloadRequest
|
} as PayloadRequest
|
||||||
setRequestContext(req)
|
setRequestContext(req)
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "المستند {{docStatus}} الحالي",
|
"currentDocumentStatus": "المستند {{docStatus}} الحالي",
|
||||||
"draft": "مسودّة",
|
"draft": "مسودّة",
|
||||||
"draftSavedSuccessfully": "تمّ حفظ المسودّة بنجاح.",
|
"draftSavedSuccessfully": "تمّ حفظ المسودّة بنجاح.",
|
||||||
"lastSavedAgo": "آخر حفظ في {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "تم الحفظ آخر مرة قبل {{distance}}",
|
||||||
"noFurtherVersionsFound": "لم يتمّ العثور على نسخات أخرى",
|
"noFurtherVersionsFound": "لم يتمّ العثور على نسخات أخرى",
|
||||||
"noRowsFound": "لم يتمّ العثور على {{label}}",
|
"noRowsFound": "لم يتمّ العثور على {{label}}",
|
||||||
"preview": "معاينة",
|
"preview": "معاينة",
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"currentDocumentStatus": "Cari {{docStatus}} sənədi",
|
"currentDocumentStatus": "Cari {{docStatus}} sənədi",
|
||||||
"draft": "Qaralama",
|
"draft": "Qaralama",
|
||||||
"draftSavedSuccessfully": "Qaralama uğurla yadda saxlandı.",
|
"draftSavedSuccessfully": "Qaralama uğurla yadda saxlandı.",
|
||||||
"lastSavedAgo": "Son yadda saxlama: {{distance, relativetime(minutes)}} əvvəl",
|
"lastSavedAgo": "{{distance}} əvvəl son yadda saxlanıldı",
|
||||||
"noFurtherVersionsFound": "Başqa versiyalar tapılmadı",
|
"noFurtherVersionsFound": "Başqa versiyalar tapılmadı",
|
||||||
"noRowsFound": "Heç bir {{label}} tapılmadı",
|
"noRowsFound": "Heç bir {{label}} tapılmadı",
|
||||||
"preview": "Öncədən baxış",
|
"preview": "Öncədən baxış",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Сегашен статус на документа: {{docStatus}}",
|
"currentDocumentStatus": "Сегашен статус на документа: {{docStatus}}",
|
||||||
"draft": "Чернова",
|
"draft": "Чернова",
|
||||||
"draftSavedSuccessfully": "Чернова запазена успешно.",
|
"draftSavedSuccessfully": "Чернова запазена успешно.",
|
||||||
"lastSavedAgo": "Последно запазен {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "последно запазено преди {{distance}}",
|
||||||
"noFurtherVersionsFound": "Не са открити повече версии",
|
"noFurtherVersionsFound": "Не са открити повече версии",
|
||||||
"noRowsFound": "Не е открит {{label}}",
|
"noRowsFound": "Не е открит {{label}}",
|
||||||
"preview": "Предварителен преглед",
|
"preview": "Предварителен преглед",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Současný {{docStatus}} dokument",
|
"currentDocumentStatus": "Současný {{docStatus}} dokument",
|
||||||
"draft": "Koncept",
|
"draft": "Koncept",
|
||||||
"draftSavedSuccessfully": "Koncept úspěšně uložen.",
|
"draftSavedSuccessfully": "Koncept úspěšně uložen.",
|
||||||
"lastSavedAgo": "Naposledy uloženo {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Naposledy uloženo před {{distance}}",
|
||||||
"noFurtherVersionsFound": "Nenalezeny další verze",
|
"noFurtherVersionsFound": "Nenalezeny další verze",
|
||||||
"noRowsFound": "Nenalezen {{label}}",
|
"noRowsFound": "Nenalezen {{label}}",
|
||||||
"preview": "Náhled",
|
"preview": "Náhled",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Aktueller Dokumentenstatus: {{docStatus}}",
|
"currentDocumentStatus": "Aktueller Dokumentenstatus: {{docStatus}}",
|
||||||
"draft": "Entwurf",
|
"draft": "Entwurf",
|
||||||
"draftSavedSuccessfully": "Entwurf erfolgreich gespeichert.",
|
"draftSavedSuccessfully": "Entwurf erfolgreich gespeichert.",
|
||||||
"lastSavedAgo": "Zuletzt gespeichert {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Zuletzt vor {{distance}} gespeichert",
|
||||||
"noFurtherVersionsFound": "Keine weiteren Versionen vorhanden",
|
"noFurtherVersionsFound": "Keine weiteren Versionen vorhanden",
|
||||||
"noRowsFound": "Kein {{label}} gefunden",
|
"noRowsFound": "Kein {{label}} gefunden",
|
||||||
"preview": "Vorschau",
|
"preview": "Vorschau",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Current {{docStatus}} document",
|
"currentDocumentStatus": "Current {{docStatus}} document",
|
||||||
"draft": "Draft",
|
"draft": "Draft",
|
||||||
"draftSavedSuccessfully": "Draft saved successfully.",
|
"draftSavedSuccessfully": "Draft saved successfully.",
|
||||||
"lastSavedAgo": "Last saved {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Last saved {{distance}} ago",
|
||||||
"noFurtherVersionsFound": "No further versions found",
|
"noFurtherVersionsFound": "No further versions found",
|
||||||
"noRowsFound": "No {{label}} found",
|
"noRowsFound": "No {{label}} found",
|
||||||
"preview": "Preview",
|
"preview": "Preview",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Documento {{docStatus}} actual",
|
"currentDocumentStatus": "Documento {{docStatus}} actual",
|
||||||
"draft": "Borrador",
|
"draft": "Borrador",
|
||||||
"draftSavedSuccessfully": "Borrador guardado con éxito.",
|
"draftSavedSuccessfully": "Borrador guardado con éxito.",
|
||||||
"lastSavedAgo": "Último guardado {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Guardado por última vez hace {{distance}}",
|
||||||
"noFurtherVersionsFound": "No se encontraron más versiones",
|
"noFurtherVersionsFound": "No se encontraron más versiones",
|
||||||
"noRowsFound": "No encontramos {{label}}",
|
"noRowsFound": "No encontramos {{label}}",
|
||||||
"preview": "Previsualizar",
|
"preview": "Previsualizar",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "جاری {{docStatus}} سند",
|
"currentDocumentStatus": "جاری {{docStatus}} سند",
|
||||||
"draft": "پیشنویس",
|
"draft": "پیشنویس",
|
||||||
"draftSavedSuccessfully": "پیشنویس با موفقیت ذخیره شد.",
|
"draftSavedSuccessfully": "پیشنویس با موفقیت ذخیره شد.",
|
||||||
"lastSavedAgo": "آخرین ذخیرهسازی {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "آخرین بار {{distance}} پیش ذخیره شد",
|
||||||
"noFurtherVersionsFound": "نگارش دیگری یافت نشد",
|
"noFurtherVersionsFound": "نگارش دیگری یافت نشد",
|
||||||
"noRowsFound": "هیچ {{label}} یافت نشد",
|
"noRowsFound": "هیچ {{label}} یافت نشد",
|
||||||
"preview": "پیشنمایش",
|
"preview": "پیشنمایش",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Document {{docStatus}} actuel",
|
"currentDocumentStatus": "Document {{docStatus}} actuel",
|
||||||
"draft": "Brouillon",
|
"draft": "Brouillon",
|
||||||
"draftSavedSuccessfully": "Brouillon enregistré avec succès.",
|
"draftSavedSuccessfully": "Brouillon enregistré avec succès.",
|
||||||
"lastSavedAgo": "Enregistré il y a de cela {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Dernière sauvegarde il y a {{distance}}",
|
||||||
"noFurtherVersionsFound": "Aucune autre version trouvée",
|
"noFurtherVersionsFound": "Aucune autre version trouvée",
|
||||||
"noRowsFound": "Aucun(e) {{label}} trouvé(e)",
|
"noRowsFound": "Aucun(e) {{label}} trouvé(e)",
|
||||||
"preview": "Aperçu",
|
"preview": "Aperçu",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Trenutni {{docStatus}} dokumenta",
|
"currentDocumentStatus": "Trenutni {{docStatus}} dokumenta",
|
||||||
"draft": "Nacrt",
|
"draft": "Nacrt",
|
||||||
"draftSavedSuccessfully": "Nacrt uspješno spremljen.",
|
"draftSavedSuccessfully": "Nacrt uspješno spremljen.",
|
||||||
"lastSavedAgo": "Zadnje spremljeno prije {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Zadnji put spremljeno prije {{distance}",
|
||||||
"noFurtherVersionsFound": "Nisu pronađene daljnje verzije",
|
"noFurtherVersionsFound": "Nisu pronađene daljnje verzije",
|
||||||
"noRowsFound": "{{label}} nije pronađeno",
|
"noRowsFound": "{{label}} nije pronađeno",
|
||||||
"preview": "Pregled",
|
"preview": "Pregled",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Jelenlegi {{docStatus}} dokumentum",
|
"currentDocumentStatus": "Jelenlegi {{docStatus}} dokumentum",
|
||||||
"draft": "Piszkozat",
|
"draft": "Piszkozat",
|
||||||
"draftSavedSuccessfully": "A piszkozat sikeresen mentve.",
|
"draftSavedSuccessfully": "A piszkozat sikeresen mentve.",
|
||||||
"lastSavedAgo": "Utoljára mentve {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Utoljára mentve {{distance}} órája",
|
||||||
"noFurtherVersionsFound": "További verziók nem találhatók",
|
"noFurtherVersionsFound": "További verziók nem találhatók",
|
||||||
"noRowsFound": "Nem található {{label}}",
|
"noRowsFound": "Nem található {{label}}",
|
||||||
"preview": "Előnézet",
|
"preview": "Előnézet",
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"currentDocumentStatus": "Documento {{docStatus}} corrente",
|
"currentDocumentStatus": "Documento {{docStatus}} corrente",
|
||||||
"draft": "Bozza",
|
"draft": "Bozza",
|
||||||
"draftSavedSuccessfully": "Bozza salvata con successo.",
|
"draftSavedSuccessfully": "Bozza salvata con successo.",
|
||||||
"lastSavedAgo": "Ultimo salvataggio {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Ultimo salvataggio {{distance}} fa",
|
||||||
"noFurtherVersionsFound": "Non sono state trovate ulteriori versioni",
|
"noFurtherVersionsFound": "Non sono state trovate ulteriori versioni",
|
||||||
"noRowsFound": "Nessun {{label}} trovato",
|
"noRowsFound": "Nessun {{label}} trovato",
|
||||||
"preview": "Anteprima",
|
"preview": "Anteprima",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "現在の {{docStatus}} データ",
|
"currentDocumentStatus": "現在の {{docStatus}} データ",
|
||||||
"draft": "ドラフト",
|
"draft": "ドラフト",
|
||||||
"draftSavedSuccessfully": "下書きは正常に保存されました。",
|
"draftSavedSuccessfully": "下書きは正常に保存されました。",
|
||||||
"lastSavedAgo": "最新の保存 {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "{{distance}}前に最後に保存されました",
|
||||||
"noFurtherVersionsFound": "その他のバージョンは見つかりませんでした。",
|
"noFurtherVersionsFound": "その他のバージョンは見つかりませんでした。",
|
||||||
"noRowsFound": "{{label}} は未設定です",
|
"noRowsFound": "{{label}} は未設定です",
|
||||||
"preview": "プレビュー",
|
"preview": "プレビュー",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "လက်ရှိ {{docStatus}} ဖိုင်",
|
"currentDocumentStatus": "လက်ရှိ {{docStatus}} ဖိုင်",
|
||||||
"draft": "မူကြမ်း",
|
"draft": "မူကြမ်း",
|
||||||
"draftSavedSuccessfully": "မူကြမ်းကို အောင်မြင်စွာ သိမ်းဆည်းပြီးပါပြီ။",
|
"draftSavedSuccessfully": "မူကြမ်းကို အောင်မြင်စွာ သိမ်းဆည်းပြီးပါပြီ။",
|
||||||
"lastSavedAgo": "နောက်ဆုံး ပြင်ဆင်ခဲ့သည်။ {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "နောက်ဆုံး သိမ်းချက် {{distance}} ကြာပြီး",
|
||||||
"noFurtherVersionsFound": "နောက်ထပ်ဗားရှင်းများ မတွေ့ပါ။",
|
"noFurtherVersionsFound": "နောက်ထပ်ဗားရှင်းများ မတွေ့ပါ။",
|
||||||
"noRowsFound": "{{label}} အားမတွေ့ပါ။",
|
"noRowsFound": "{{label}} အားမတွေ့ပါ။",
|
||||||
"preview": "နမူနာပြရန်",
|
"preview": "နမူနာပြရန်",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Nåværende {{docStatus}} dokument",
|
"currentDocumentStatus": "Nåværende {{docStatus}} dokument",
|
||||||
"draft": "Utkast",
|
"draft": "Utkast",
|
||||||
"draftSavedSuccessfully": "Utkast lagret.",
|
"draftSavedSuccessfully": "Utkast lagret.",
|
||||||
"lastSavedAgo": "Sist lagret {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Sist lagret {{distance}} siden",
|
||||||
"noFurtherVersionsFound": "Ingen flere versjoner funnet",
|
"noFurtherVersionsFound": "Ingen flere versjoner funnet",
|
||||||
"noRowsFound": "Ingen {{label}} funnet",
|
"noRowsFound": "Ingen {{label}} funnet",
|
||||||
"preview": "Forhåndsvisning",
|
"preview": "Forhåndsvisning",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Huidig {{docStatus}} document",
|
"currentDocumentStatus": "Huidig {{docStatus}} document",
|
||||||
"draft": "Concept",
|
"draft": "Concept",
|
||||||
"draftSavedSuccessfully": "Concept succesvol bewaard.",
|
"draftSavedSuccessfully": "Concept succesvol bewaard.",
|
||||||
"lastSavedAgo": "Laatst bewaard {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Laatst opgeslagen {{distance}} geleden",
|
||||||
"noFurtherVersionsFound": "Geen verdere versies gevonden",
|
"noFurtherVersionsFound": "Geen verdere versies gevonden",
|
||||||
"noRowsFound": "Geen {{label}} gevonden",
|
"noRowsFound": "Geen {{label}} gevonden",
|
||||||
"preview": "Voorbeeld",
|
"preview": "Voorbeeld",
|
||||||
|
|||||||
@@ -334,7 +334,7 @@
|
|||||||
"currentDocumentStatus": "Bieżący status {{docStatus}} dokumentu",
|
"currentDocumentStatus": "Bieżący status {{docStatus}} dokumentu",
|
||||||
"draft": "Szkic",
|
"draft": "Szkic",
|
||||||
"draftSavedSuccessfully": "Wersja robocza została pomyślnie zapisana.",
|
"draftSavedSuccessfully": "Wersja robocza została pomyślnie zapisana.",
|
||||||
"lastSavedAgo": "Ostatnio zapisano {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Ostatnio zapisane {{distance}} temu",
|
||||||
"noFurtherVersionsFound": "Nie znaleziono dalszych wersji",
|
"noFurtherVersionsFound": "Nie znaleziono dalszych wersji",
|
||||||
"noRowsFound": "Nie znaleziono {{label}}",
|
"noRowsFound": "Nie znaleziono {{label}}",
|
||||||
"preview": "Podgląd",
|
"preview": "Podgląd",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Documento {{docStatus}} atual",
|
"currentDocumentStatus": "Documento {{docStatus}} atual",
|
||||||
"draft": "Rascunho",
|
"draft": "Rascunho",
|
||||||
"draftSavedSuccessfully": "Rascunho salvo com sucesso.",
|
"draftSavedSuccessfully": "Rascunho salvo com sucesso.",
|
||||||
"lastSavedAgo": "Salvo pela última vez {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Última gravação há {{distance}}",
|
||||||
"noFurtherVersionsFound": "Nenhuma outra versão encontrada",
|
"noFurtherVersionsFound": "Nenhuma outra versão encontrada",
|
||||||
"noRowsFound": "Nenhum(a) {{label}} encontrado(a)",
|
"noRowsFound": "Nenhum(a) {{label}} encontrado(a)",
|
||||||
"preview": "Pré-visualização",
|
"preview": "Pré-visualização",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Documentul {{docStatus}} curent",
|
"currentDocumentStatus": "Documentul {{docStatus}} curent",
|
||||||
"draft": "Proiect",
|
"draft": "Proiect",
|
||||||
"draftSavedSuccessfully": "Proiect salvat cu succes.",
|
"draftSavedSuccessfully": "Proiect salvat cu succes.",
|
||||||
"lastSavedAgo": "Ultima salvare {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Ultima salvare acum {{distance}}",
|
||||||
"noFurtherVersionsFound": "Nu s-au găsit alte versiuni",
|
"noFurtherVersionsFound": "Nu s-au găsit alte versiuni",
|
||||||
"noRowsFound": "Nu s-a găsit niciun {{label}}",
|
"noRowsFound": "Nu s-a găsit niciun {{label}}",
|
||||||
"preview": "Previzualizare",
|
"preview": "Previzualizare",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Текущий статус {{docStatus}} документа",
|
"currentDocumentStatus": "Текущий статус {{docStatus}} документа",
|
||||||
"draft": "Черновик",
|
"draft": "Черновик",
|
||||||
"draftSavedSuccessfully": "Черновик успешно сохранен.",
|
"draftSavedSuccessfully": "Черновик успешно сохранен.",
|
||||||
"lastSavedAgo": "Последнее сохранение было {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Последний раз сохранено {{distance}} назад",
|
||||||
"noFurtherVersionsFound": "Другие версии не найдены",
|
"noFurtherVersionsFound": "Другие версии не найдены",
|
||||||
"noRowsFound": "Не найдено {{label}}",
|
"noRowsFound": "Не найдено {{label}}",
|
||||||
"preview": "Предпросмотр",
|
"preview": "Предпросмотр",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Nuvarande {{docStatus}} dokument",
|
"currentDocumentStatus": "Nuvarande {{docStatus}} dokument",
|
||||||
"draft": "Utkast",
|
"draft": "Utkast",
|
||||||
"draftSavedSuccessfully": "Utkastet sparades framgångsrikt.",
|
"draftSavedSuccessfully": "Utkastet sparades framgångsrikt.",
|
||||||
"lastSavedAgo": "Sparades senast {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Senast sparad för {{distance}} sedan",
|
||||||
"noFurtherVersionsFound": "Inga fler versioner hittades",
|
"noFurtherVersionsFound": "Inga fler versioner hittades",
|
||||||
"noRowsFound": "Inga {{label}} hittades",
|
"noRowsFound": "Inga {{label}} hittades",
|
||||||
"preview": "Förhandsvisa",
|
"preview": "Förhandsvisa",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "เอกสารปัจจุบัน",
|
"currentDocumentStatus": "เอกสารปัจจุบัน",
|
||||||
"draft": "ฉบับร่าง",
|
"draft": "ฉบับร่าง",
|
||||||
"draftSavedSuccessfully": "บันทึกร่างสำเร็จ",
|
"draftSavedSuccessfully": "บันทึกร่างสำเร็จ",
|
||||||
"lastSavedAgo": "บันทึกล่าสุดเมื่อ {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "บันทึกครั้งล่าสุด {{distance}} ที่ผ่านมา",
|
||||||
"noFurtherVersionsFound": "ไม่พบเวอร์ชันอื่น ๆ",
|
"noFurtherVersionsFound": "ไม่พบเวอร์ชันอื่น ๆ",
|
||||||
"noRowsFound": "ไม่พบ {{label}}",
|
"noRowsFound": "ไม่พบ {{label}}",
|
||||||
"preview": "ตัวอย่าง",
|
"preview": "ตัวอย่าง",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Şu an {{docStatus}} döküman",
|
"currentDocumentStatus": "Şu an {{docStatus}} döküman",
|
||||||
"draft": "Taslak",
|
"draft": "Taslak",
|
||||||
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
|
"draftSavedSuccessfully": "Taslak başarıyla kaydedildi.",
|
||||||
"lastSavedAgo": "Son kaydedilme: {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Son kaydedildi {{distance}} önce",
|
||||||
"noFurtherVersionsFound": "Başka sürüm bulunamadı.",
|
"noFurtherVersionsFound": "Başka sürüm bulunamadı.",
|
||||||
"noRowsFound": "{{label}} bulunamadı",
|
"noRowsFound": "{{label}} bulunamadı",
|
||||||
"preview": "Önizleme",
|
"preview": "Önizleme",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Поточний статус {{docStatus}} документа",
|
"currentDocumentStatus": "Поточний статус {{docStatus}} документа",
|
||||||
"draft": "Чернетка",
|
"draft": "Чернетка",
|
||||||
"draftSavedSuccessfully": "Чернетка успішно збережена.",
|
"draftSavedSuccessfully": "Чернетка успішно збережена.",
|
||||||
"lastSavedAgo": "Останній запис {{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "Останній раз збережено {{distance}} тому",
|
||||||
"noFurtherVersionsFound": "Інших версій не знайдено",
|
"noFurtherVersionsFound": "Інших версій не знайдено",
|
||||||
"noRowsFound": "Не знайдено {{label}}",
|
"noRowsFound": "Не знайдено {{label}}",
|
||||||
"preview": "Попередній перегляд",
|
"preview": "Попередній перегляд",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "Trạng thái tài liệu hiện tại: {{docStatus}}",
|
"currentDocumentStatus": "Trạng thái tài liệu hiện tại: {{docStatus}}",
|
||||||
"draft": "Bản nháp",
|
"draft": "Bản nháp",
|
||||||
"draftSavedSuccessfully": "Bản nháp đã được lưu thành công.",
|
"draftSavedSuccessfully": "Bản nháp đã được lưu thành công.",
|
||||||
"lastSavedAgo": "Bản lưu mới nhất: {{distance, relativetime(minutes)}} trước",
|
"lastSavedAgo": "Lần lưu cuối cùng {{distance}} trước đây",
|
||||||
"noFurtherVersionsFound": "Không tìm thấy phiên bản cũ hơn",
|
"noFurtherVersionsFound": "Không tìm thấy phiên bản cũ hơn",
|
||||||
"noRowsFound": "Không tìm thấy: {{label}}",
|
"noRowsFound": "Không tìm thấy: {{label}}",
|
||||||
"preview": "Bản xem trước",
|
"preview": "Bản xem trước",
|
||||||
|
|||||||
@@ -333,7 +333,7 @@
|
|||||||
"currentDocumentStatus": "当前{{docStatus}}文件",
|
"currentDocumentStatus": "当前{{docStatus}}文件",
|
||||||
"draft": "草稿",
|
"draft": "草稿",
|
||||||
"draftSavedSuccessfully": "草稿成功保存。",
|
"draftSavedSuccessfully": "草稿成功保存。",
|
||||||
"lastSavedAgo": "最后一次保存{{distance, relativetime(minutes)}}",
|
"lastSavedAgo": "上次保存{{distance}}之前",
|
||||||
"noFurtherVersionsFound": "没有发现其他版本",
|
"noFurtherVersionsFound": "没有发现其他版本",
|
||||||
"noRowsFound": "没有发现{{label}}",
|
"noRowsFound": "没有发现{{label}}",
|
||||||
"preview": "预览",
|
"preview": "预览",
|
||||||
|
|||||||
@@ -217,11 +217,11 @@ export default async function resizeAndTransformImageSizes({
|
|||||||
const maxOffsetX = Math.max(info.width - width, 0)
|
const maxOffsetX = Math.max(info.width - width, 0)
|
||||||
const maxOffsetY = Math.max(info.height - height, 0)
|
const maxOffsetY = Math.max(info.height - height, 0)
|
||||||
|
|
||||||
const focalPointX = Math.floor(info.width * focalPoint.x - width / 2)
|
const focalPointX = Math.floor((info.width / 100) * focalPoint.x)
|
||||||
const focalPointY = Math.floor(info.height * focalPoint.y - height / 2)
|
const focalPointY = Math.floor((info.height / 100) * focalPoint.y)
|
||||||
|
|
||||||
const offsetX = Math.min(Math.max(focalPointX, 0), maxOffsetX)
|
const offsetX = Math.min(Math.max(focalPointX - width / 2, 0), maxOffsetX)
|
||||||
const offsetY = Math.min(Math.max(focalPointY, 0), maxOffsetY)
|
const offsetY = Math.min(Math.max(focalPointY - height / 2, 0), maxOffsetY)
|
||||||
|
|
||||||
resized = resized.extract({
|
resized = resized.extract({
|
||||||
height,
|
height,
|
||||||
|
|||||||
37
packages/plugin-nested-docs/.eslintrc.cjs
Normal file
37
packages/plugin-nested-docs/.eslintrc.cjs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/** @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,
|
||||||
|
}
|
||||||
3
packages/plugin-nested-docs/.eslintrc.js
Normal file
3
packages/plugin-nested-docs/.eslintrc.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ['@payloadcms'],
|
||||||
|
}
|
||||||
6
packages/plugin-nested-docs/.gitignore
vendored
Normal file
6
packages/plugin-nested-docs/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
.DS_Store
|
||||||
|
package-lock.json
|
||||||
10
packages/plugin-nested-docs/.prettierignore
Normal file
10
packages/plugin-nested-docs/.prettierignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.tmp
|
||||||
|
**/.git
|
||||||
|
**/.hg
|
||||||
|
**/.pnp.*
|
||||||
|
**/.svn
|
||||||
|
**/.yarn/**
|
||||||
|
**/build
|
||||||
|
**/dist/**
|
||||||
|
**/node_modules
|
||||||
|
**/temp
|
||||||
15
packages/plugin-nested-docs/.swcrc
Normal file
15
packages/plugin-nested-docs/.swcrc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/swcrc",
|
||||||
|
"sourceMaps": "inline",
|
||||||
|
"jsc": {
|
||||||
|
"target": "esnext",
|
||||||
|
"parser": {
|
||||||
|
"syntax": "typescript",
|
||||||
|
"tsx": true,
|
||||||
|
"dts": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
248
packages/plugin-nested-docs/README.md
Normal file
248
packages/plugin-nested-docs/README.md
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
# Payload Nested Docs Plugin
|
||||||
|
|
||||||
|
[](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
|
||||||
2
packages/plugin-nested-docs/fields.d.ts
vendored
Normal file
2
packages/plugin-nested-docs/fields.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './dist/fields/breadcrumbs';
|
||||||
|
export * from './dist/fields/parent';
|
||||||
7
packages/plugin-nested-docs/fields.js
Normal file
7
packages/plugin-nested-docs/fields.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const breadcrumbs = require('./dist/fields/breadcrumbs');
|
||||||
|
const parent = require('./dist/fields/parent');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
breadcrumbs,
|
||||||
|
parent
|
||||||
|
};
|
||||||
42
packages/plugin-nested-docs/package.json
Normal file
42
packages/plugin-nested-docs/package.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
]
|
||||||
|
}
|
||||||
49
packages/plugin-nested-docs/src/fields/breadcrumbs.ts
Normal file
49
packages/plugin-nested-docs/src/fields/breadcrumbs.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
32
packages/plugin-nested-docs/src/fields/parent.ts
Normal file
32
packages/plugin-nested-docs/src/fields/parent.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
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
|
||||||
56
packages/plugin-nested-docs/src/hooks/resaveChildren.ts
Normal file
56
packages/plugin-nested-docs/src/hooks/resaveChildren.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
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
|
||||||
49
packages/plugin-nested-docs/src/index.ts
Normal file
49
packages/plugin-nested-docs/src/index.ts
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
23
packages/plugin-nested-docs/src/types.ts
Normal file
23
packages/plugin-nested-docs/src/types.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
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
|
||||||
47
packages/plugin-nested-docs/src/utilities/getParents.ts
Normal file
47
packages/plugin-nested-docs/src/utilities/getParents.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
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
|
||||||
25
packages/plugin-nested-docs/tsconfig.json
Normal file
25
packages/plugin-nested-docs/tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
1
packages/plugin-nested-docs/types.d.ts
vendored
Normal file
1
packages/plugin-nested-docs/types.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './dist/types';
|
||||||
1
packages/plugin-nested-docs/types.js
Normal file
1
packages/plugin-nested-docs/types.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require('./dist/types');
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/richtext-lexical",
|
"name": "@payloadcms/richtext-lexical",
|
||||||
"version": "0.1.11",
|
"version": "0.1.12",
|
||||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||||
"repository": "https://github.com/payloadcms/payload",
|
"repository": "https://github.com/payloadcms/payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ export const LinkDrawer: React.FC<Props> = ({
|
|||||||
initialState,
|
initialState,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation('fields')
|
const { t } = useTranslation('fields')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer className={baseClass} slug={drawerSlug} title={t('editLink') ?? ''}>
|
<Drawer className={baseClass} slug={drawerSlug} title={t('editLink') ?? ''}>
|
||||||
<Form initialState={initialState} onSubmit={handleModalSubmit}>
|
<Form fields={fieldSchema} initialState={initialState} onSubmit={handleModalSubmit}>
|
||||||
<RenderFields
|
<RenderFields
|
||||||
fieldSchema={fieldSchema}
|
fieldSchema={fieldSchema}
|
||||||
fieldTypes={fieldTypes}
|
fieldTypes={fieldTypes}
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ export function transformExtraFields(
|
|||||||
|
|
||||||
// Wrap fields which are not part of the base schema in a group named 'fields' - otherwise they will be rendered but not saved
|
// Wrap fields which are not part of the base schema in a group named 'fields' - otherwise they will be rendered but not saved
|
||||||
const extraFields = []
|
const extraFields = []
|
||||||
fields.forEach((field) => {
|
for (let i = fields.length - 1; i >= 0; i--) {
|
||||||
|
const field = fields[i]
|
||||||
|
|
||||||
if ('name' in field) {
|
if ('name' in field) {
|
||||||
if (
|
if (
|
||||||
!baseFields.find((baseField) => !('name' in baseField) || baseField.name === field.name)
|
!baseFields.find((baseField) => !('name' in baseField) || baseField.name === field.name)
|
||||||
@@ -35,7 +37,7 @@ export function transformExtraFields(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
if (Array.isArray(customFieldSchema) || fields.length > 0) {
|
if (Array.isArray(customFieldSchema) || fields.length > 0) {
|
||||||
// find field with name 'fields' and add the extra fields to it
|
// find field with name 'fields' and add the extra fields to it
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
.rich-text-lexical {
|
.rich-text-lexical {
|
||||||
display: flex;
|
display: flex;
|
||||||
isolation: isolate;
|
|
||||||
|
|
||||||
.errorBoundary {
|
.errorBoundary {
|
||||||
pre {
|
pre {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
tab-size: 1;
|
tab-size: 1;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
|
isolation: isolate;
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@payloadcms/richtext-slate",
|
"name": "@payloadcms/richtext-slate",
|
||||||
"version": "1.0.5",
|
"version": "1.0.6",
|
||||||
"description": "The officially supported Slate richtext adapter for Payload",
|
"description": "The officially supported Slate richtext adapter for Payload",
|
||||||
"repository": "https://github.com/payloadcms/payload",
|
"repository": "https://github.com/payloadcms/payload",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const LinkDrawer: React.FC<Props> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer className={baseClass} slug={drawerSlug} title={t('editLink')}>
|
<Drawer className={baseClass} slug={drawerSlug} title={t('editLink')}>
|
||||||
<Form initialState={initialState} onSubmit={handleModalSubmit}>
|
<Form fields={fieldSchema} initialState={initialState} onSubmit={handleModalSubmit}>
|
||||||
<RenderFields
|
<RenderFields
|
||||||
fieldSchema={fieldSchema}
|
fieldSchema={fieldSchema}
|
||||||
fieldTypes={fieldTypes}
|
fieldTypes={fieldTypes}
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ export function transformExtraFields(
|
|||||||
|
|
||||||
// Wrap fields which are not part of the base schema in a group named 'fields' - otherwise they will be rendered but not saved
|
// Wrap fields which are not part of the base schema in a group named 'fields' - otherwise they will be rendered but not saved
|
||||||
const extraFields = []
|
const extraFields = []
|
||||||
fields.forEach((field) => {
|
for (let i = fields.length - 1; i >= 0; i--) {
|
||||||
|
const field = fields[i]
|
||||||
|
|
||||||
if ('name' in field) {
|
if ('name' in field) {
|
||||||
if (
|
if (
|
||||||
!baseFields.find((baseField) => !('name' in baseField) || baseField.name === field.name)
|
!baseFields.find((baseField) => !('name' in baseField) || baseField.name === field.name)
|
||||||
@@ -76,7 +78,7 @@ export function transformExtraFields(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
if (Array.isArray(customFieldSchema) || fields.length > 0) {
|
if (Array.isArray(customFieldSchema) || fields.length > 0) {
|
||||||
fields.push({
|
fields.push({
|
||||||
|
|||||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@@ -60,6 +60,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
|
'@types/semver':
|
||||||
|
specifier: ^7.5.3
|
||||||
|
version: 7.5.3
|
||||||
'@types/shelljs':
|
'@types/shelljs':
|
||||||
specifier: 0.8.12
|
specifier: 0.8.12
|
||||||
version: 0.8.12
|
version: 0.8.12
|
||||||
@@ -96,6 +99,9 @@ importers:
|
|||||||
glob:
|
glob:
|
||||||
specifier: 8.1.0
|
specifier: 8.1.0
|
||||||
version: 8.1.0
|
version: 8.1.0
|
||||||
|
graphql-request:
|
||||||
|
specifier: 6.1.0
|
||||||
|
version: 6.1.0(graphql@16.8.1)
|
||||||
husky:
|
husky:
|
||||||
specifier: ^8.0.3
|
specifier: ^8.0.3
|
||||||
version: 8.0.3
|
version: 8.0.3
|
||||||
@@ -138,6 +144,9 @@ importers:
|
|||||||
rimraf:
|
rimraf:
|
||||||
specifier: 3.0.2
|
specifier: 3.0.2
|
||||||
version: 3.0.2
|
version: 3.0.2
|
||||||
|
semver:
|
||||||
|
specifier: ^7.5.4
|
||||||
|
version: 7.5.4
|
||||||
shelljs:
|
shelljs:
|
||||||
specifier: 0.8.5
|
specifier: 0.8.5
|
||||||
version: 0.8.5
|
version: 0.8.5
|
||||||
@@ -940,9 +949,6 @@ importers:
|
|||||||
get-port:
|
get-port:
|
||||||
specifier: 5.1.1
|
specifier: 5.1.1
|
||||||
version: 5.1.1
|
version: 5.1.1
|
||||||
graphql-request:
|
|
||||||
specifier: 6.1.0
|
|
||||||
version: 6.1.0(graphql@16.8.1)
|
|
||||||
mini-css-extract-plugin:
|
mini-css-extract-plugin:
|
||||||
specifier: 1.6.2
|
specifier: 1.6.2
|
||||||
version: 1.6.2(webpack@5.88.2)
|
version: 1.6.2(webpack@5.88.2)
|
||||||
@@ -1035,6 +1041,15 @@ importers:
|
|||||||
specifier: ^5.78.0
|
specifier: ^5.78.0
|
||||||
version: 5.88.2(@swc/core@1.3.78)(webpack-cli@4.10.0)
|
version: 5.88.2(@swc/core@1.3.78)(webpack-cli@4.10.0)
|
||||||
|
|
||||||
|
packages/plugin-nested-docs:
|
||||||
|
devDependencies:
|
||||||
|
'@payloadcms/eslint-config':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../eslint-config-payload
|
||||||
|
payload:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../payload
|
||||||
|
|
||||||
packages/richtext-lexical:
|
packages/richtext-lexical:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@faceless-ui/modal':
|
'@faceless-ui/modal':
|
||||||
@@ -5786,6 +5801,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==}
|
resolution: {integrity: sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/semver@7.5.3:
|
||||||
|
resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/send@0.17.1:
|
/@types/send@0.17.1:
|
||||||
resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==}
|
resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
79
scripts/lib/getPackageDetails.ts
Normal file
79
scripts/lib/getPackageDetails.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import fse from 'fs-extra'
|
||||||
|
import chalk from 'chalk'
|
||||||
|
import chalkTemplate from 'chalk-template'
|
||||||
|
import simpleGit from 'simple-git'
|
||||||
|
|
||||||
|
const git = simpleGit()
|
||||||
|
const packagesDir = path.resolve(__dirname, '../../packages')
|
||||||
|
|
||||||
|
export type PackageDetails = {
|
||||||
|
name: string
|
||||||
|
newCommits: number
|
||||||
|
shortName: string
|
||||||
|
packagePath: string
|
||||||
|
publishedVersion: string
|
||||||
|
publishDate: string
|
||||||
|
version: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getPackageDetails = async (): Promise<PackageDetails[]> => {
|
||||||
|
const packageDirs = fse.readdirSync(packagesDir).filter((d) => d !== 'eslint-config-payload')
|
||||||
|
const packageDetails = await Promise.all(
|
||||||
|
packageDirs.map(async (dirName) => {
|
||||||
|
const packageJson = await fse.readJson(`${packagesDir}/${dirName}/package.json`)
|
||||||
|
const isPublic = packageJson.private !== true
|
||||||
|
if (!isPublic) return null
|
||||||
|
|
||||||
|
// Get published version from npm
|
||||||
|
const json = await fetch(`https://registry.npmjs.org/${packageJson.name}`).then((res) =>
|
||||||
|
res.json(),
|
||||||
|
)
|
||||||
|
|
||||||
|
const publishedVersion = json?.['dist-tags']?.latest
|
||||||
|
const publishDate = json?.time?.[publishedVersion]
|
||||||
|
|
||||||
|
const prevGitTag = `${dirName}/${packageJson.version}`
|
||||||
|
const prevGitTagHash = await git.revparse(prevGitTag)
|
||||||
|
|
||||||
|
const newCommits = await git.log({
|
||||||
|
from: prevGitTagHash,
|
||||||
|
file: `packages/${dirName}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: packageJson.name as string,
|
||||||
|
newCommits: newCommits.total,
|
||||||
|
shortName: dirName,
|
||||||
|
packagePath: `packages/${dirName}`,
|
||||||
|
publishedVersion,
|
||||||
|
publishDate,
|
||||||
|
version: packageJson.version,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return packageDetails.filter((p): p is Exclude<typeof p, null> => p !== null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showPackageDetails = (details: PackageDetails[]) => {
|
||||||
|
console.log(chalkTemplate`
|
||||||
|
|
||||||
|
{bold Packages:}
|
||||||
|
|
||||||
|
${details
|
||||||
|
.map((p) => {
|
||||||
|
const name = p?.newCommits ? chalk.bold.green(p?.shortName.padEnd(28)) : p?.shortName.padEnd(28)
|
||||||
|
const publishData = `${p?.publishedVersion} at ${p?.publishDate
|
||||||
|
.split(':')
|
||||||
|
.slice(0, 2)
|
||||||
|
.join(':')
|
||||||
|
.replace('T', ' ')}`
|
||||||
|
const newCommits = `${p?.newCommits ? `${chalk.bold.green(p?.newCommits)} new commits` : ''}`
|
||||||
|
|
||||||
|
return ` ${name}${publishData} ${newCommits}`
|
||||||
|
})
|
||||||
|
.join('\n')}
|
||||||
|
|
||||||
|
`)
|
||||||
|
}
|
||||||
@@ -1,74 +1,10 @@
|
|||||||
import path from 'path'
|
import { getPackageDetails, showPackageDetails } from './lib/getPackageDetails'
|
||||||
import fse from 'fs-extra'
|
|
||||||
import chalk from 'chalk'
|
|
||||||
import chalkTemplate from 'chalk-template'
|
|
||||||
import simpleGit from 'simple-git'
|
|
||||||
|
|
||||||
const git = simpleGit()
|
|
||||||
|
|
||||||
const packagesDir = path.resolve(__dirname, '../packages')
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// List all public packages excluding eslint-config-payload
|
const packageDetails = await getPackageDetails()
|
||||||
const packageDirs = fse.readdirSync(packagesDir).filter((d) => d !== 'eslint-config-payload')
|
showPackageDetails(packageDetails)
|
||||||
const packageDetails = await Promise.all(
|
|
||||||
packageDirs.map(async (dirName) => {
|
|
||||||
const packageJson = await fse.readJson(`${packagesDir}/${dirName}/package.json`)
|
|
||||||
const isPublic = packageJson.private !== true
|
|
||||||
if (!isPublic) return null
|
|
||||||
|
|
||||||
// Get published version from npm
|
|
||||||
const json = await fetch(`https://registry.npmjs.org/${packageJson.name}`).then((res) =>
|
|
||||||
res.json(),
|
|
||||||
)
|
|
||||||
|
|
||||||
const publishedVersion = json?.['dist-tags']?.latest
|
|
||||||
const publishDate = json?.time?.[publishedVersion]
|
|
||||||
|
|
||||||
const prevGitTag = `${dirName}/${packageJson.version}`
|
|
||||||
const prevGitTagHash = await git.revparse(prevGitTag)
|
|
||||||
|
|
||||||
const newCommits = await git.log({
|
|
||||||
from: prevGitTagHash,
|
|
||||||
file: `packages/${dirName}`,
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: packageJson.name,
|
|
||||||
newCommits: newCommits.total,
|
|
||||||
packageDir: dirName,
|
|
||||||
packagePath: `packages/${dirName}`,
|
|
||||||
publishedVersion,
|
|
||||||
publishDate,
|
|
||||||
version: packageJson.version,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
console.log(chalkTemplate`
|
|
||||||
|
|
||||||
{bold Packages:}
|
|
||||||
|
|
||||||
${packageDetails
|
|
||||||
.map((p) => {
|
|
||||||
const name = p?.newCommits
|
|
||||||
? chalk.bold.green(p?.packageDir.padEnd(28))
|
|
||||||
: p?.packageDir.padEnd(28)
|
|
||||||
const publishData = `${p?.publishedVersion} at ${p?.publishDate
|
|
||||||
.split(':')
|
|
||||||
.slice(0, 2)
|
|
||||||
.join(':')
|
|
||||||
.replace('T', ' ')}`
|
|
||||||
const newCommits = `${p?.newCommits ? `${chalk.bold.green(p?.newCommits)} new commits` : ''}`
|
|
||||||
|
|
||||||
return ` ${name}${publishData} ${newCommits}`
|
|
||||||
})
|
|
||||||
.join('\n')}
|
|
||||||
|
|
||||||
`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(packageNames)
|
|
||||||
|
|
||||||
main().catch((error) => {
|
main().catch((error) => {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
|
|||||||
@@ -4,32 +4,54 @@ import chalk from 'chalk'
|
|||||||
import prompts from 'prompts'
|
import prompts from 'prompts'
|
||||||
import minimist from 'minimist'
|
import minimist from 'minimist'
|
||||||
import chalkTemplate from 'chalk-template'
|
import chalkTemplate from 'chalk-template'
|
||||||
|
import { PackageDetails, getPackageDetails, showPackageDetails } from './lib/getPackageDetails'
|
||||||
|
import semver from 'semver'
|
||||||
|
|
||||||
const execOpts: ExecSyncOptions = { stdio: 'inherit' }
|
const execOpts: ExecSyncOptions = { stdio: 'inherit' }
|
||||||
const args = minimist(process.argv.slice(2))
|
const args = minimist(process.argv.slice(2))
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const { _: packageNames, tag = 'latest', bump = 'patch' } = args
|
const { tag = 'latest', bump = 'patch' } = args
|
||||||
|
|
||||||
if (packageNames.length === 0) {
|
if (!semver.RELEASE_TYPES.includes(bump)) {
|
||||||
|
abort(`Invalid bump type: ${bump}.\n\nMust be one of: ${semver.RELEASE_TYPES.join(', ')}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const packageDetails = await getPackageDetails()
|
||||||
|
showPackageDetails(packageDetails)
|
||||||
|
|
||||||
|
const { packagesToRelease } = (await prompts({
|
||||||
|
type: 'multiselect',
|
||||||
|
name: 'packagesToRelease',
|
||||||
|
message: 'Select packages to release',
|
||||||
|
instructions: 'Space to select. Enter to submit.',
|
||||||
|
choices: packageDetails.map((p) => {
|
||||||
|
const title = p?.newCommits ? chalk.bold.green(p?.shortName) : p?.shortName
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
value: p.shortName,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})) as { packagesToRelease: string[] }
|
||||||
|
|
||||||
|
if (!packagesToRelease) {
|
||||||
|
abort()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packagesToRelease.length === 0) {
|
||||||
abort('Please specify a package to publish')
|
abort('Please specify a package to publish')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packageNames.find((p) => p === 'payload' && packageNames.length > 1)) {
|
if (packagesToRelease.find((p) => p === 'payload' && packagesToRelease.length > 1)) {
|
||||||
abort('Cannot publish payload with other packages')
|
abort('Cannot publish payload with other packages. Release Payload first.')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current version of each package from package.json
|
const packageMap = packageDetails.reduce(
|
||||||
const packageDetails = await Promise.all(
|
(acc, p) => {
|
||||||
packageNames.map(async (packageName) => {
|
acc[p.shortName] = p
|
||||||
const packageDir = `packages/${packageName}`
|
return acc
|
||||||
if (!(await fse.pathExists(packageDir))) {
|
},
|
||||||
abort(`Package path ${packageDir} does not exist`)
|
{} as Record<string, PackageDetails>,
|
||||||
}
|
|
||||||
const packageObj = await fse.readJson(`${packageDir}/package.json`)
|
|
||||||
|
|
||||||
return { name: packageName, version: packageObj.version, dir: packageDir }
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
console.log(chalkTemplate`
|
console.log(chalkTemplate`
|
||||||
@@ -38,10 +60,15 @@ async function main() {
|
|||||||
{bold.yellow Bump: ${bump}}
|
{bold.yellow Bump: ${bump}}
|
||||||
{bold.yellow Tag: ${tag}}
|
{bold.yellow Tag: ${tag}}
|
||||||
|
|
||||||
${packageDetails.map((p) => ` ${p.name} - current: ${p.version}`).join('\n')}
|
${packagesToRelease
|
||||||
|
.map((p) => {
|
||||||
|
const { shortName, version } = packageMap[p]
|
||||||
|
return ` ${shortName.padEnd(24)} ${version} -> ${semver.inc(version, bump)}`
|
||||||
|
})
|
||||||
|
.join('\n')}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
const confirmPublish = await confirm(`Publish ${packageNames.length} package(s)?`)
|
const confirmPublish = await confirm(`Publish ${packagesToRelease.length} package(s)?`)
|
||||||
|
|
||||||
if (!confirmPublish) {
|
if (!confirmPublish) {
|
||||||
abort()
|
abort()
|
||||||
@@ -49,26 +76,26 @@ ${packageDetails.map((p) => ` ${p.name} - current: ${p.version}`).join('\n')}
|
|||||||
|
|
||||||
const results: { name: string; success: boolean }[] = []
|
const results: { name: string; success: boolean }[] = []
|
||||||
|
|
||||||
for (const pkg of packageDetails) {
|
for (const pkg of packagesToRelease) {
|
||||||
const { dir, name } = pkg
|
const { packagePath, shortName } = packageMap[pkg]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(chalk.bold(`\n\nPublishing ${name}...\n\n`))
|
console.log(chalk.bold(`\n\nPublishing ${shortName}...\n\n`))
|
||||||
|
|
||||||
execSync(`npm --no-git-tag-version --prefix ${dir} version ${bump}`, execOpts)
|
execSync(`npm --no-git-tag-version --prefix ${packagePath} version ${bump}`, execOpts)
|
||||||
execSync(`git add ${dir}/package.json`, execOpts)
|
execSync(`git add ${packagePath}/package.json`, execOpts)
|
||||||
|
|
||||||
const packageObj = await fse.readJson(`${dir}/package.json`)
|
const packageObj = await fse.readJson(`${packagePath}/package.json`)
|
||||||
const newVersion = packageObj.version
|
const newVersion = packageObj.version
|
||||||
|
|
||||||
const tagName = `${name}/${newVersion}`
|
const tagName = `${shortName}/${newVersion}`
|
||||||
execSync(`git commit -m "chore(release): ${tagName}"`, execOpts)
|
execSync(`git commit -m "chore(release): ${tagName}"`, execOpts)
|
||||||
execSync(`git tag -a ${tagName} -m "${tagName}"`, execOpts)
|
execSync(`git tag -a ${tagName} -m "${tagName}"`, execOpts)
|
||||||
execSync(`pnpm publish -C ${dir} --no-git-checks`, execOpts)
|
execSync(`pnpm publish -C ${packagePath} --no-git-checks`, execOpts)
|
||||||
results.push({ name, success: true })
|
results.push({ name: shortName, success: true })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(chalk.bold.red(`ERROR: ${error.message}`))
|
console.error(chalk.bold.red(`ERROR: ${error.message}`))
|
||||||
results.push({ name, success: false })
|
results.push({ name: shortName, success: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
templates/ecommerce/.vscode/launch.json
vendored
Normal file
14
templates/ecommerce/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "yarn dev",
|
||||||
|
"name": "Debug Ecommerce",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"@payloadcms/bundler-webpack": "^1.0.0",
|
"@payloadcms/bundler-webpack": "^1.0.0",
|
||||||
"@payloadcms/db-mongodb": "^1.0.0",
|
"@payloadcms/db-mongodb": "^1.0.0",
|
||||||
"@payloadcms/plugin-cloud": "^2.0.0",
|
"@payloadcms/plugin-cloud": "^2.0.0",
|
||||||
"@payloadcms/plugin-nested-docs": "^1.0.4",
|
"@payloadcms/plugin-nested-docs": "^1.0.8",
|
||||||
"@payloadcms/plugin-redirects": "^1.0.0",
|
"@payloadcms/plugin-redirects": "^1.0.0",
|
||||||
"@payloadcms/plugin-seo": "^1.0.10",
|
"@payloadcms/plugin-seo": "^1.0.10",
|
||||||
"@payloadcms/plugin-stripe": "^0.0.14",
|
"@payloadcms/plugin-stripe": "^0.0.14",
|
||||||
@@ -35,10 +35,10 @@
|
|||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"qs": "6.11.2",
|
|
||||||
"next": "^13.4.8",
|
"next": "^13.4.8",
|
||||||
"payload": "^2.0.0",
|
"payload": "^2.0.7",
|
||||||
"payload-admin-bar": "^1.0.6",
|
"payload-admin-bar": "^1.0.6",
|
||||||
|
"qs": "6.11.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.45.1",
|
"react-hook-form": "^7.45.1",
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/eslint-plugin-next": "^13.1.6",
|
"@next/eslint-plugin-next": "^13.1.6",
|
||||||
"@payloadcms/eslint-config": "^0.0.1",
|
"@payloadcms/eslint-config": "^0.0.1",
|
||||||
|
"@swc/core": "1.3.76",
|
||||||
"@types/escape-html": "^1.0.2",
|
"@types/escape-html": "^1.0.2",
|
||||||
"@types/express": "^4.17.9",
|
"@types/express": "^4.17.9",
|
||||||
"@swc/core": "1.3.76",
|
|
||||||
"@types/node": "18.11.3",
|
"@types/node": "18.11.3",
|
||||||
"@types/qs": "^6.9.8",
|
"@types/qs": "^6.9.8",
|
||||||
"@types/react": "18.0.21",
|
"@types/react": "18.0.21",
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ export const cartPage: Partial<Page> = {
|
|||||||
link: {
|
link: {
|
||||||
type: 'reference',
|
type: 'reference',
|
||||||
url: '',
|
url: '',
|
||||||
reference: {
|
reference: null,
|
||||||
relationTo: 'pages',
|
|
||||||
value: '',
|
|
||||||
},
|
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
richText: [
|
richText: [
|
||||||
|
|||||||
@@ -141,10 +141,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -196,10 +193,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -251,10 +245,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -281,10 +272,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -310,10 +298,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -339,10 +324,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -368,10 +350,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -410,10 +389,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
@@ -439,10 +415,7 @@ export const home: Partial<Page> = {
|
|||||||
],
|
],
|
||||||
enableLink: false,
|
enableLink: false,
|
||||||
link: {
|
link: {
|
||||||
reference: {
|
reference: null,
|
||||||
value: '',
|
|
||||||
relationTo: 'pages',
|
|
||||||
},
|
|
||||||
url: '',
|
url: '',
|
||||||
label: '',
|
label: '',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -72,6 +72,16 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
let image1ID = image1Doc.id
|
||||||
|
let image2ID = image2Doc.id
|
||||||
|
let image3ID = image3Doc.id
|
||||||
|
|
||||||
|
if (payload.db.defaultIDType === 'text') {
|
||||||
|
image1ID = `"${image1ID}"`
|
||||||
|
image2ID = `"${image2ID}"`
|
||||||
|
image3ID = `"${image3ID}"`
|
||||||
|
}
|
||||||
|
|
||||||
payload.logger.info(`— Seeding categories...`)
|
payload.logger.info(`— Seeding categories...`)
|
||||||
|
|
||||||
const [apparelCategory, ebooksCategory, coursesCategory] = await Promise.all([
|
const [apparelCategory, ebooksCategory, coursesCategory] = await Promise.all([
|
||||||
@@ -103,8 +113,8 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
collection: 'products',
|
collection: 'products',
|
||||||
data: JSON.parse(
|
data: JSON.parse(
|
||||||
JSON.stringify({ ...product1, categories: [apparelCategory.id] }).replace(
|
JSON.stringify({ ...product1, categories: [apparelCategory.id] }).replace(
|
||||||
/{{PRODUCT_IMAGE}}/g,
|
/"\{\{PRODUCT_IMAGE\}\}"/g,
|
||||||
image1Doc.id,
|
image1ID,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -113,8 +123,8 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
collection: 'products',
|
collection: 'products',
|
||||||
data: JSON.parse(
|
data: JSON.parse(
|
||||||
JSON.stringify({ ...product2, categories: [ebooksCategory.id] }).replace(
|
JSON.stringify({ ...product2, categories: [ebooksCategory.id] }).replace(
|
||||||
/{{PRODUCT_IMAGE}}/g,
|
/"\{\{PRODUCT_IMAGE\}\}"/g,
|
||||||
image2Doc.id,
|
image2ID,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -123,8 +133,8 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
collection: 'products',
|
collection: 'products',
|
||||||
data: JSON.parse(
|
data: JSON.parse(
|
||||||
JSON.stringify({ ...product3, categories: [coursesCategory.id] }).replace(
|
JSON.stringify({ ...product3, categories: [coursesCategory.id] }).replace(
|
||||||
/{{PRODUCT_IMAGE}}/g,
|
/"\{\{PRODUCT_IMAGE\}\}"/g,
|
||||||
image3Doc.id,
|
image3ID,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
@@ -157,20 +167,24 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
|
|
||||||
payload.logger.info(`— Seeding products page...`)
|
payload.logger.info(`— Seeding products page...`)
|
||||||
|
|
||||||
const { id: productsPageID } = await payload.create({
|
let { id: productsPageID } = await payload.create({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
data: productsPage,
|
data: productsPage,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (payload.db.defaultIDType === 'text') {
|
||||||
|
productsPageID = `"${productsPageID}"`
|
||||||
|
}
|
||||||
|
|
||||||
payload.logger.info(`— Seeding home page...`)
|
payload.logger.info(`— Seeding home page...`)
|
||||||
|
|
||||||
await payload.create({
|
await payload.create({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
data: JSON.parse(
|
data: JSON.parse(
|
||||||
JSON.stringify(home)
|
JSON.stringify(home)
|
||||||
.replace(/{{PRODUCT1_IMAGE}}/g, image1Doc.id)
|
.replace(/"\{\{PRODUCT1_IMAGE\}\}"/g, image1ID)
|
||||||
.replace(/{{PRODUCT2_IMAGE}}/g, image2Doc.id)
|
.replace(/"\{\{PRODUCT2_IMAGE\}\}"/g, image2ID)
|
||||||
.replace(/{{PRODUCTS_PAGE_ID}}/g, productsPageID),
|
.replace(/"\{\{PRODUCTS_PAGE_ID\}\}"/g, productsPageID),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -178,7 +192,9 @@ export const seed = async (payload: Payload): Promise<void> => {
|
|||||||
|
|
||||||
await payload.create({
|
await payload.create({
|
||||||
collection: 'pages',
|
collection: 'pages',
|
||||||
data: JSON.parse(JSON.stringify(cartPage).replace(/{{PRODUCTS_PAGE_ID}}/g, productsPageID)),
|
data: JSON.parse(
|
||||||
|
JSON.stringify(cartPage).replace(/"\{\{PRODUCTS_PAGE_ID\}\}"/g, productsPageID),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
payload.logger.info(`— Seeding settings...`)
|
payload.logger.info(`— Seeding settings...`)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user