Compare commits
610 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1a15f6e33 | ||
|
|
9037e6c64b | ||
|
|
604922a26e | ||
|
|
0117f18eb1 | ||
|
|
a715a4206e | ||
|
|
6e83edc988 | ||
|
|
9f1ebaf850 | ||
|
|
8571dc3965 | ||
|
|
5b8c721292 | ||
|
|
e2248a066d | ||
|
|
62dea6d52a | ||
|
|
fe380bd943 | ||
|
|
b266ae1356 | ||
|
|
4abcad67b7 | ||
|
|
0243371c71 | ||
|
|
15323a6b6d | ||
|
|
f5b9d32317 | ||
|
|
71ed0ad0ca | ||
|
|
b4fd2b1976 | ||
|
|
b6d2c95ee7 | ||
|
|
238232cf51 | ||
|
|
04cf39749b | ||
|
|
c9616b01ac | ||
|
|
dede06ad76 | ||
|
|
843d65f494 | ||
|
|
58788c327f | ||
|
|
0124ae8812 | ||
|
|
3d08222c29 | ||
|
|
f6c0251a6c | ||
|
|
cf32ee460c | ||
|
|
569ce08174 | ||
|
|
e2d370a415 | ||
|
|
152799ecc7 | ||
|
|
087ac31533 | ||
|
|
b184b26a4e | ||
|
|
f86e90b072 | ||
|
|
be04310810 | ||
|
|
d510961f6c | ||
|
|
d29f6775a8 | ||
|
|
7be836cced | ||
|
|
4528586849 | ||
|
|
47e82cb069 | ||
|
|
d38c6f8118 | ||
|
|
757c8647bf | ||
|
|
ba6c1b9439 | ||
|
|
ac92e1289b | ||
|
|
6a49bffa9a | ||
|
|
a95aada35a | ||
|
|
8fd430819b | ||
|
|
396760d523 | ||
|
|
6ab15fce1c | ||
|
|
81ca30c9d4 | ||
|
|
a5085b6e56 | ||
|
|
4cb8bbd2f4 | ||
|
|
b9c597af92 | ||
|
|
47b6bb683b | ||
|
|
d3df6c606c | ||
|
|
1cd578ef44 | ||
|
|
55dd4768b9 | ||
|
|
66946c8697 | ||
|
|
1e4e6e9619 | ||
|
|
c97fb62228 | ||
|
|
cd5a24e308 | ||
|
|
c17a03ef60 | ||
|
|
abfad8c088 | ||
|
|
82b4042b26 | ||
|
|
1129711f75 | ||
|
|
69582b2e8c | ||
|
|
00821bf0a2 | ||
|
|
4a313ee7c3 | ||
|
|
85f3a8b038 | ||
|
|
5fe4cb9eee | ||
|
|
0e120093cf | ||
|
|
064ab8846d | ||
|
|
1d5338a8dc | ||
|
|
4ac08dac65 | ||
|
|
41df1c447f | ||
|
|
808a283f74 | ||
|
|
be69ff5849 | ||
|
|
9d94c509e7 | ||
|
|
282f575cab | ||
|
|
6b61714d7e | ||
|
|
dc8ffa34e4 | ||
|
|
8c8c49c66d | ||
|
|
bb7c829c5e | ||
|
|
6bf60ff5d6 | ||
|
|
100d1e7220 | ||
|
|
c97732cef3 | ||
|
|
c398c8b2a2 | ||
|
|
cee40169f3 | ||
|
|
7d3b6d12e3 | ||
|
|
98b62df792 | ||
|
|
e2d9cd1eed | ||
|
|
f873a84f08 | ||
|
|
c1b1b81774 | ||
|
|
7333cc25d8 | ||
|
|
32957833f3 | ||
|
|
20fabb81e8 | ||
|
|
7644b031c1 | ||
|
|
dbc403319d | ||
|
|
c1d025e241 | ||
|
|
c3c3f3fc88 | ||
|
|
6f1d61aabc | ||
|
|
3d282d2523 | ||
|
|
ba66a0e801 | ||
|
|
0fcd3d8f28 | ||
|
|
ddda183090 | ||
|
|
f19fc9057d | ||
|
|
17e4d78bdc | ||
|
|
9ef954f430 | ||
|
|
767b68b0bd | ||
|
|
53d78e995b | ||
|
|
0119965287 | ||
|
|
45dc3cab11 | ||
|
|
73d27be947 | ||
|
|
a5bbb338b9 | ||
|
|
fd7cd0324d | ||
|
|
aa795d19d5 | ||
|
|
9019cc9101 | ||
|
|
cd64238a51 | ||
|
|
5ffa0ed6ee | ||
|
|
1889f00f8f | ||
|
|
0e2fbe0e8f | ||
|
|
70a84d90ad | ||
|
|
56072e952d | ||
|
|
f88f482837 | ||
|
|
ca55c4e55f | ||
|
|
a00809db8e | ||
|
|
e930abe741 | ||
|
|
b584d22b3a | ||
|
|
254524ab1b | ||
|
|
472a6cb232 | ||
|
|
ed8d7f2106 | ||
|
|
4239f8e592 | ||
|
|
55deb3f01b | ||
|
|
d09fba47f1 | ||
|
|
2420969375 | ||
|
|
055ff455fe | ||
|
|
f3be1fcc62 | ||
|
|
ec00edcdad | ||
|
|
e36be704a5 | ||
|
|
75e557b894 | ||
|
|
41a26289b3 | ||
|
|
c9cb1ea05c | ||
|
|
b3f326fead | ||
|
|
a1f4168d50 | ||
|
|
8d946f225e | ||
|
|
26a01afa1a | ||
|
|
35686a7dca | ||
|
|
34942daf94 | ||
|
|
0bdd159fb9 | ||
|
|
d6e7211539 | ||
|
|
713673bc42 | ||
|
|
d75da16fef | ||
|
|
cfdacea210 | ||
|
|
924eb1d0b5 | ||
|
|
6fcf4ebc48 | ||
|
|
badd59ac38 | ||
|
|
5b6392009d | ||
|
|
777a2292dc | ||
|
|
352f70a9e4 | ||
|
|
09f267c378 | ||
|
|
c2d2702a59 | ||
|
|
062771e0a7 | ||
|
|
d2571fa798 | ||
|
|
eafc0876a1 | ||
|
|
56ce92e012 | ||
|
|
51958c25ac | ||
|
|
8789dae155 | ||
|
|
d10f3f140f | ||
|
|
7670a23611 | ||
|
|
53811b2324 | ||
|
|
3344656e6a | ||
|
|
e4eece0352 | ||
|
|
2a4b821c34 | ||
|
|
4a4c4223e6 | ||
|
|
314ea43e6d | ||
|
|
fdbdf93250 | ||
|
|
cb33417924 | ||
|
|
cbf12524fe | ||
|
|
8b34cab19a | ||
|
|
05a99b5798 | ||
|
|
f1a83de772 | ||
|
|
eb3d299521 | ||
|
|
60afdd239c | ||
|
|
307840edd1 | ||
|
|
95b8df6d70 | ||
|
|
700f28c3ac | ||
|
|
1487c3ff16 | ||
|
|
b94772bfcd | ||
|
|
44d79d2153 | ||
|
|
09f3008569 | ||
|
|
e5043e73e3 | ||
|
|
16d308f452 | ||
|
|
3e9ad427ec | ||
|
|
16d0289c36 | ||
|
|
894a400b86 | ||
|
|
9134b51985 | ||
|
|
e00321a101 | ||
|
|
75d0b5bb50 | ||
|
|
b774d09b4b | ||
|
|
a91451e946 | ||
|
|
983bf713b3 | ||
|
|
f0ac9d6935 | ||
|
|
d2572ba4e4 | ||
|
|
51307f29c5 | ||
|
|
a608a799aa | ||
|
|
e7822f7a51 | ||
|
|
e3277cf120 | ||
|
|
2ffb2b5200 | ||
|
|
18698a9f18 | ||
|
|
95c96247d9 | ||
|
|
f2f65952b2 | ||
|
|
afe5f16af0 | ||
|
|
6a7da1e603 | ||
|
|
bc9adb9fe5 | ||
|
|
9e1153639e | ||
|
|
59e5a73e49 | ||
|
|
8d1856ae2d | ||
|
|
1eeee4854a | ||
|
|
3bea32883d | ||
|
|
4f2891836e | ||
|
|
63e86c4147 | ||
|
|
dfc77f0a3f | ||
|
|
1aaed161eb | ||
|
|
7d411622c6 | ||
|
|
a106fa62fe | ||
|
|
551c249e39 | ||
|
|
38028dd36b | ||
|
|
5b22d91579 | ||
|
|
09b9ce60ad | ||
|
|
e20a07e06f | ||
|
|
0204aa962c | ||
|
|
d46051435f | ||
|
|
0d56cf4496 | ||
|
|
61dae53fc3 | ||
|
|
f5377120c4 | ||
|
|
780106c7f6 | ||
|
|
811e4bb265 | ||
|
|
111cab1564 | ||
|
|
131dd51c39 | ||
|
|
0d333ce7da | ||
|
|
fa7ad6e9ed | ||
|
|
9b6dd0c771 | ||
|
|
a7a0624235 | ||
|
|
8f08269916 | ||
|
|
dbd305acc5 | ||
|
|
83d32e4449 | ||
|
|
78d7aa7707 | ||
|
|
a3ecd7324a | ||
|
|
87525001f7 | ||
|
|
f52836a7e3 | ||
|
|
fe536f0628 | ||
|
|
1de5ac8cba | ||
|
|
2624ad5f7e | ||
|
|
7fb23ab6be | ||
|
|
208e6fe47a | ||
|
|
9a1c1f64c0 | ||
|
|
65fe6c2f95 | ||
|
|
65ade57c94 | ||
|
|
2565005cc0 | ||
|
|
de4538bf5f | ||
|
|
2b80020393 | ||
|
|
1166e85fad | ||
|
|
e5193476c4 | ||
|
|
5dbf276e82 | ||
|
|
a6f3230915 | ||
|
|
0694a09abd | ||
|
|
dceeeaac6a | ||
|
|
bdc92bcdf0 | ||
|
|
06a6056e1c | ||
|
|
4b951279a8 | ||
|
|
3984f8b36c | ||
|
|
b9b3a0dcc7 | ||
|
|
7caa025278 | ||
|
|
27e5dc4d55 | ||
|
|
63fc9b76be | ||
|
|
5c1e2846a2 | ||
|
|
73c45944f4 | ||
|
|
86171c500f | ||
|
|
1010334f76 | ||
|
|
f44869f7cb | ||
|
|
4b0c5cc9a2 | ||
|
|
36b8f46f7e | ||
|
|
d5ecbc96a3 | ||
|
|
760114b718 | ||
|
|
76068637fb | ||
|
|
bed0b1c04e | ||
|
|
8a1cdc3f7d | ||
|
|
462f7f1f42 | ||
|
|
10a657e9d7 | ||
|
|
ae7a94bf47 | ||
|
|
e12bdb320d | ||
|
|
f667937aef | ||
|
|
20c508cb12 | ||
|
|
c00e5e8904 | ||
|
|
c6b00c9aca | ||
|
|
7154a1e35c | ||
|
|
734662a9b4 | ||
|
|
b11aa62001 | ||
|
|
f4c066e475 | ||
|
|
1d7a789604 | ||
|
|
3f74eff0fe | ||
|
|
2a2d33cd0b | ||
|
|
4e61ae84f7 | ||
|
|
165634d127 | ||
|
|
082c6d010c | ||
|
|
62f65d5ffb | ||
|
|
738698edad | ||
|
|
a83064ed97 | ||
|
|
5ef407ba17 | ||
|
|
21fabfcb29 | ||
|
|
521f250688 | ||
|
|
df33ceca79 | ||
|
|
0ffbd2ee0f | ||
|
|
4d64569c34 | ||
|
|
32c025a2fa | ||
|
|
58fa48a4da | ||
|
|
699aa1b60f | ||
|
|
a00c565a62 | ||
|
|
90bac7f4ab | ||
|
|
ec2cda20cf | ||
|
|
1702261a15 | ||
|
|
bd85d621f5 | ||
|
|
61bc485bf1 | ||
|
|
eaf89794ab | ||
|
|
6a6b23d3d6 | ||
|
|
5bb8a6d6d5 | ||
|
|
cc73db9bf0 | ||
|
|
48d2e230a3 | ||
|
|
0ac24bc4f2 | ||
|
|
29e148763a | ||
|
|
354d1527e1 | ||
|
|
ffa56e6c81 | ||
|
|
edcc6b56c8 | ||
|
|
7e2f3e21ba | ||
|
|
0d238085ba | ||
|
|
082bf2fba4 | ||
|
|
56a3ccaee8 | ||
|
|
3f4c66467d | ||
|
|
85ccd80906 | ||
|
|
de539d00b6 | ||
|
|
f37c9eec04 | ||
|
|
9fd3e8d84f | ||
|
|
07c917e33d | ||
|
|
10c51f11c5 | ||
|
|
5431b8ebcc | ||
|
|
e233551d0b | ||
|
|
5d4d1bf60c | ||
|
|
e6bfe00843 | ||
|
|
5c3b20643a | ||
|
|
e9600802a8 | ||
|
|
0aa2e5138c | ||
|
|
27dad40d5c | ||
|
|
646b46528d | ||
|
|
e097e924f2 | ||
|
|
777aaf9afd | ||
|
|
221ec0bb10 | ||
|
|
67ff273a9e | ||
|
|
397d36291d | ||
|
|
a4066e4802 | ||
|
|
88e24ba452 | ||
|
|
c7b377b84c | ||
|
|
05a06a9aa8 | ||
|
|
90a686ea0b | ||
|
|
215df7ff9e | ||
|
|
0758f01120 | ||
|
|
bb7a910377 | ||
|
|
078293833d | ||
|
|
99f61150d6 | ||
|
|
ac64013a07 | ||
|
|
5735b4bbec | ||
|
|
f0374d5772 | ||
|
|
20a9dcf6fe | ||
|
|
d0ef42a16b | ||
|
|
18077d98bf | ||
|
|
cda4792ff7 | ||
|
|
76df2bc75a | ||
|
|
e52b639e64 | ||
|
|
75604e9b6c | ||
|
|
e058933192 | ||
|
|
a12ae0a1b6 | ||
|
|
5e0fd00b4e | ||
|
|
b4a43475ac | ||
|
|
f0bc59dd0c | ||
|
|
c5aba71aa7 | ||
|
|
cac6a8869b | ||
|
|
787691859d | ||
|
|
bf0d20461a | ||
|
|
7da73626ac | ||
|
|
8086120703 | ||
|
|
7afa815467 | ||
|
|
5400500360 | ||
|
|
ccae4014ec | ||
|
|
02279a769d | ||
|
|
c766a5a40e | ||
|
|
7ac2d0dcff | ||
|
|
6dfa1616ea | ||
|
|
8a0411d6b1 | ||
|
|
fc63a692be | ||
|
|
2b9b504573 | ||
|
|
fd9453889e | ||
|
|
dea21a0aae | ||
|
|
12c520c3b1 | ||
|
|
abc0383ecc | ||
|
|
bb4dce09df | ||
|
|
6b932168ce | ||
|
|
681bba82a9 | ||
|
|
4cfde3eba7 | ||
|
|
71633b1c8d | ||
|
|
2eb863aff0 | ||
|
|
5aede8affb | ||
|
|
09dfb9793a | ||
|
|
09897de77d | ||
|
|
0362290d40 | ||
|
|
57ef9fe623 | ||
|
|
38f08d54e3 | ||
|
|
84191ec8fd | ||
|
|
e88be6b251 | ||
|
|
3bec424d05 | ||
|
|
fc56a42fb0 | ||
|
|
05a5cc16bd | ||
|
|
c99b2f35f4 | ||
|
|
8ae7457a3f | ||
|
|
bb8a04dd7b | ||
|
|
a681f5f725 | ||
|
|
613552de0a | ||
|
|
cd38d37242 | ||
|
|
6b6b503ef0 | ||
|
|
f880072697 | ||
|
|
ffc3f10177 | ||
|
|
f9b7e3239e | ||
|
|
09cc61c96a | ||
|
|
a6325c69f4 | ||
|
|
2f1b1a02b1 | ||
|
|
727c5a4a53 | ||
|
|
918d3bd2bc | ||
|
|
2d7bacad09 | ||
|
|
234ed07ad6 | ||
|
|
964fdf779a | ||
|
|
40afb5e8fa | ||
|
|
72c0145816 | ||
|
|
12eb33b5c9 | ||
|
|
ddb238c7e4 | ||
|
|
32980fcafc | ||
|
|
db6315a621 | ||
|
|
6bf0c2aab6 | ||
|
|
3dc9ddcb52 | ||
|
|
352dfa9a09 | ||
|
|
60a3e680dd | ||
|
|
18f98e24e5 | ||
|
|
c599522e44 | ||
|
|
64fef7d380 | ||
|
|
6381d4cf6b | ||
|
|
91016ec206 | ||
|
|
9aeab9548d | ||
|
|
69d7f21b56 | ||
|
|
9de596605b | ||
|
|
650edcf56a | ||
|
|
2c4dedff2c | ||
|
|
870e39961c | ||
|
|
319148ca68 | ||
|
|
6dac68606b | ||
|
|
9716d008a9 | ||
|
|
b5fd68c3dc | ||
|
|
eea9d14749 | ||
|
|
77de6e4b60 | ||
|
|
58f68e3bda | ||
|
|
1ea3763185 | ||
|
|
920251f296 | ||
|
|
dffb554ebe | ||
|
|
7255f6108f | ||
|
|
078392f2c5 | ||
|
|
c2e9407f50 | ||
|
|
a5a4f1490e | ||
|
|
e20555f9cf | ||
|
|
791a222d28 | ||
|
|
cb97090d88 | ||
|
|
923cdc7b6a | ||
|
|
19369b4c33 | ||
|
|
4ec230e8a0 | ||
|
|
7aafe49662 | ||
|
|
33d8ec8a13 | ||
|
|
fb73e772af | ||
|
|
c2692e9b4a | ||
|
|
a0d6fe5ca7 | ||
|
|
7f65e68e82 | ||
|
|
d9f78fc5bf | ||
|
|
b2a5279bcb | ||
|
|
28baba822b | ||
|
|
3b4875b754 | ||
|
|
8ce88deda2 | ||
|
|
4527658027 | ||
|
|
8057c0ecb8 | ||
|
|
eb74a42386 | ||
|
|
d589a90a42 | ||
|
|
bf3d05cb40 | ||
|
|
7bd4859a31 | ||
|
|
9af097c39c | ||
|
|
7f47cdacbb | ||
|
|
d85cbde7a7 | ||
|
|
79284941db | ||
|
|
35c11aa7aa | ||
|
|
5ac2b1fb3d | ||
|
|
0a5e8ab618 | ||
|
|
5ae267f743 | ||
|
|
bc48e92aea | ||
|
|
98af494dd6 | ||
|
|
31487fb022 | ||
|
|
e00a2eeef7 | ||
|
|
c5ea2dcd2a | ||
|
|
e9c2b46c97 | ||
|
|
043d3fffbf | ||
|
|
febe213e80 | ||
|
|
0764f34c64 | ||
|
|
3dbf9ac27c | ||
|
|
eccb4383a1 | ||
|
|
31180bfc2b | ||
|
|
c6105d9ed3 | ||
|
|
3b82d1ccba | ||
|
|
9fe8a09ac9 | ||
|
|
18a59f84ab | ||
|
|
c28f78cb8a | ||
|
|
18baefed0d | ||
|
|
f56eeddff4 | ||
|
|
f5561b4b4f | ||
|
|
d42171d465 | ||
|
|
f3d56fe435 | ||
|
|
52e9e4daa7 | ||
|
|
dde76572e3 | ||
|
|
df4563274b | ||
|
|
6e93bd006e | ||
|
|
814cc9658c | ||
|
|
efc6d0adf1 | ||
|
|
f37fe42c70 | ||
|
|
3359cd4e9b | ||
|
|
2b80c5fda6 | ||
|
|
4c2bcb2933 | ||
|
|
96c1362a5d | ||
|
|
5f3b1aec0a | ||
|
|
942afd96fe | ||
|
|
39ddde082c | ||
|
|
9b384e8192 | ||
|
|
09543831b9 | ||
|
|
eb0b5870a3 | ||
|
|
49c03135a9 | ||
|
|
22ba992b6d | ||
|
|
553d3ebd48 | ||
|
|
f80bda89b6 | ||
|
|
722f2fc88d | ||
|
|
c89d2e0f01 | ||
|
|
7aab4214b7 | ||
|
|
6294333c88 | ||
|
|
98afd9c53b | ||
|
|
6ccca08319 | ||
|
|
f497fdde22 | ||
|
|
d73fdf6572 | ||
|
|
0e6f790734 | ||
|
|
18774c05ea | ||
|
|
b3dda3c070 | ||
|
|
d9e62e9a6d | ||
|
|
3f5518aa3a | ||
|
|
0c12b8dfda | ||
|
|
a53ac62164 | ||
|
|
8fa63c7131 | ||
|
|
5599b8bd30 | ||
|
|
5694258b74 | ||
|
|
a974c908b5 | ||
|
|
6d7d996d61 | ||
|
|
da4d9c5e71 | ||
|
|
c409ac985c | ||
|
|
62072e2d0f | ||
|
|
18e08ad5a7 | ||
|
|
ae8cc7b9ed | ||
|
|
06fd32786d | ||
|
|
2f5c13aac3 | ||
|
|
5025972450 | ||
|
|
e7d3f77560 | ||
|
|
f171adc88d | ||
|
|
e24428c42c | ||
|
|
e849f0f49e | ||
|
|
b011163d90 | ||
|
|
0492603ac7 | ||
|
|
15a488c03f | ||
|
|
77096cb252 | ||
|
|
6efeafe819 | ||
|
|
dabc5749d4 | ||
|
|
79fc3f72a6 | ||
|
|
7c2de28de9 | ||
|
|
83f77d3a05 | ||
|
|
5b71a3cb60 | ||
|
|
04650a86a5 | ||
|
|
69b4f9f59f | ||
|
|
4df979565e | ||
|
|
193cdbbe5e | ||
|
|
a634a5c00c | ||
|
|
c19ccd5df4 | ||
|
|
57c6afa3a9 | ||
|
|
9354d86af2 | ||
|
|
791de301cc | ||
|
|
87ccdae795 | ||
|
|
a412e68e89 | ||
|
|
98e2f2be08 | ||
|
|
b8b5ca17ed | ||
|
|
96ccebdedd | ||
|
|
59da900a1d | ||
|
|
fbc4429648 | ||
|
|
3feec809e6 | ||
|
|
8dd3298f9a | ||
|
|
0c3986917f |
@@ -4,7 +4,7 @@ charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.js]
|
||||
[*.{js,ts,tsx}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
|
||||
68
.eslintrc.js
68
.eslintrc.js
@@ -1,16 +1,62 @@
|
||||
module.exports = {
|
||||
parser: "babel-eslint",
|
||||
extends: "@trbl",
|
||||
rules: {
|
||||
"import/no-unresolved": [
|
||||
2,
|
||||
{
|
||||
ignore: [
|
||||
'payload/config',
|
||||
'payload/unsanitizedConfig',
|
||||
]
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
extends: [
|
||||
'@trbl',
|
||||
],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
rules: {
|
||||
"no-shadow": "off",
|
||||
"@typescript-eslint/no-shadow": ["error"],
|
||||
'import/no-unresolved': [
|
||||
2,
|
||||
{
|
||||
ignore: [
|
||||
'payload/config',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
"import/no-extraneous-dependencies": ["error", { "packageDir": "./" }],
|
||||
'react/jsx-filename-extension': [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
|
||||
'import/prefer-default-export': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'react/no-unused-prop-types': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'ignorePackages',
|
||||
{
|
||||
js: 'never',
|
||||
jsx: 'never',
|
||||
ts: 'never',
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
@@ -15,6 +15,9 @@ jobs:
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org
|
||||
scope: '@payloadcms'
|
||||
always-auth: true
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
@@ -25,6 +28,9 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: yarn
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- run: yarn test:client
|
||||
- run: yarn test:int # In-memory db + api tests
|
||||
env:
|
||||
CI: true
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -215,10 +215,16 @@ $RECYCLE.BIN/
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
|
||||
# End of https://www.gitignore.io/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
|
||||
# Ignore all uploads
|
||||
demo/upload
|
||||
demo/media
|
||||
demo/files
|
||||
|
||||
# Ignore build folder
|
||||
build
|
||||
|
||||
# Ignore built components
|
||||
components/index.js
|
||||
components/styles.css
|
||||
|
||||
49
.vscode/launch.json
vendored
49
.vscode/launch.json
vendored
@@ -23,37 +23,40 @@
|
||||
"<node_internals>/**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Debug Jest Test - Current File",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeArgs": [
|
||||
"--inspect-brk",
|
||||
"${workspaceRoot}/node_modules/.bin/jest",
|
||||
"${fileBasename}",
|
||||
"--runInBand"
|
||||
],
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "demo/payload.config.js"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"port": 9229,
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "demo/payload.config.js"
|
||||
"PAYLOAD_CONFIG_PATH": "demo/payload.config.ts",
|
||||
"BABEL_ENV": "development"
|
||||
},
|
||||
"program": "${workspaceFolder}/demo/server.js",
|
||||
"program": "${workspaceFolder}/demo/index.js",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
]
|
||||
],
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program - Production",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "demo/payload.config.ts",
|
||||
"NODE_ENV": "production",
|
||||
"BABEL_ENV": "development"
|
||||
},
|
||||
"program": "${workspaceFolder}/demo/index.js",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
|
||||
"runtimeArgs": [
|
||||
"--nolazy"
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as Popup } from '../src/client/components/elements/Popup';
|
||||
|
||||
export { default as MinimalTemplate } from '../src/client/components/templates/Minimal';
|
||||
@@ -1 +0,0 @@
|
||||
export { default as Button } from '../src/client/components/elements/Button';
|
||||
@@ -1,6 +0,0 @@
|
||||
export { default as Form } from '../src/client/components/forms/Form';
|
||||
export { default as Text } from '../src/client/components/forms/field-types/Text';
|
||||
export { default as Select } from '../src/client/components/forms/field-types/Select';
|
||||
export { default as Checkbox } from '../src/client/components/forms/field-types/Checkbox';
|
||||
export { default as Submit } from '../src/client/components/forms/Submit';
|
||||
export { default as reduceFieldsToValues } from '../src/client/components/forms/Form/reduceFieldsToValues';
|
||||
@@ -1 +0,0 @@
|
||||
export { default as X } from '../src/client/components/icons/X';
|
||||
@@ -1,4 +0,0 @@
|
||||
export { default as LeafButton } from '../src/client/components/forms/field-types/RichText/LeafButton';
|
||||
export { default as ElementButton } from '../src/client/components/forms/field-types/RichText/ElementButton';
|
||||
|
||||
export { default as toggleElement } from '../src/client/components/forms/field-types/RichText/toggleElement';
|
||||
@@ -1 +0,0 @@
|
||||
@import '../src/client/scss/styles.scss';
|
||||
@@ -1,21 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
require.resolve('@babel/preset-env'),
|
||||
{
|
||||
modules: 'cjs',
|
||||
targets: [
|
||||
'defaults',
|
||||
'not IE 11',
|
||||
'not IE_Mob 11',
|
||||
],
|
||||
},
|
||||
],
|
||||
require.resolve('@babel/preset-react'),
|
||||
],
|
||||
plugins: [
|
||||
require.resolve('@babel/plugin-proposal-class-properties'),
|
||||
require.resolve('@babel/plugin-proposal-optional-chaining'),
|
||||
require.resolve('babel-plugin-add-module-exports'),
|
||||
],
|
||||
};
|
||||
const config = require('./src/babel.config');
|
||||
|
||||
module.exports = config;
|
||||
|
||||
19
components/forms.js
Normal file
19
components/forms.js
Normal file
@@ -0,0 +1,19 @@
|
||||
export {
|
||||
useForm,
|
||||
useWatchForm,
|
||||
useFormSubmitted,
|
||||
useFormProcessing,
|
||||
useFormModified,
|
||||
} from '../src/admin/components/forms/Form/context';
|
||||
|
||||
export { default as useFieldType } from '../src/admin/components/forms/useFieldType';
|
||||
|
||||
export { default as Form } from '../src/admin/components/forms/Form';
|
||||
|
||||
export { default as Text } from '../src/admin/components/forms/field-types/Text';
|
||||
export { default as Group } from '../src/admin/components/forms/field-types/Group';
|
||||
export { default as Select } from '../src/admin/components/forms/field-types/Select';
|
||||
export { default as Checkbox } from '../src/admin/components/forms/field-types/Checkbox';
|
||||
export { default as Submit } from '../src/admin/components/forms/Submit';
|
||||
|
||||
export { default as reduceFieldsToValues } from '../src/admin/components/forms/Form/reduceFieldsToValues';
|
||||
3
components/rich-text.js
Normal file
3
components/rich-text.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as LeafButton } from '../src/admin/components/forms/field-types/RichText/leaves/Button';
|
||||
export { default as ElementButton } from '../src/admin/components/forms/field-types/RichText/elements/Button';
|
||||
export { default as toggleElement } from '../src/admin/components/forms/field-types/RichText/elements/toggle';
|
||||
2
components/views.js
Normal file
2
components/views.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as Edit } from '../src/admin/components/views/collections/Edit/Default';
|
||||
export { default as List } from '../src/admin/components/views/collections/List/Default';
|
||||
2
config.d.ts
vendored
Normal file
2
config.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export { buildConfig } from './dist/config/build';
|
||||
export * from './dist/config/types';
|
||||
1
config.js
Normal file
1
config.js
Normal file
@@ -0,0 +1 @@
|
||||
exports.buildConfig = require('./dist/config/build').buildConfig;
|
||||
@@ -6,11 +6,7 @@
|
||||
*/
|
||||
const checkRole = (allRoles, user) => {
|
||||
if (user) {
|
||||
if (allRoles.some((role) => {
|
||||
return user.roles && user.roles.some((individualRole) => {
|
||||
return individualRole === role;
|
||||
});
|
||||
})) {
|
||||
if (allRoles.some((role) => user.roles && user.roles.some((individualRole) => individualRole === role))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -18,4 +14,4 @@ const checkRole = (allRoles, user) => {
|
||||
return false;
|
||||
};
|
||||
|
||||
module.exports = checkRole;
|
||||
export default checkRole;
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = [
|
||||
export default [
|
||||
'admin',
|
||||
'editor',
|
||||
'moderator',
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { Block } from '../../src/fields/config/types';
|
||||
|
||||
const CTA: Block = {
|
||||
slug: 'cta',
|
||||
labels: {
|
||||
singular: 'Call to Action',
|
||||
@@ -16,8 +18,9 @@ module.exports = {
|
||||
name: 'url',
|
||||
label: 'URL',
|
||||
type: 'text',
|
||||
height: 100,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default CTA;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { Block } from '../../src/fields/config/types';
|
||||
|
||||
const Email: Block = {
|
||||
slug: 'email',
|
||||
labels: {
|
||||
singular: 'Email',
|
||||
@@ -9,8 +11,9 @@ module.exports = {
|
||||
name: 'testEmail',
|
||||
label: 'Test Email Field',
|
||||
type: 'email',
|
||||
maxLength: 100,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default Email;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { Block } from '../../src/fields/config/types';
|
||||
|
||||
const NumberBlock: Block = {
|
||||
slug: 'number',
|
||||
labels: {
|
||||
singular: 'Number',
|
||||
@@ -9,8 +11,10 @@ module.exports = {
|
||||
name: 'testNumber',
|
||||
label: 'Test Number Field',
|
||||
type: 'number',
|
||||
maxLength: 100,
|
||||
max: 100,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default NumberBlock;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { Block } from '../../src/fields/config/types';
|
||||
|
||||
const Quote: Block = {
|
||||
blockImage: '/static/assets/images/generic-block-image.svg',
|
||||
slug: 'quote',
|
||||
labels: {
|
||||
@@ -17,7 +19,6 @@ module.exports = {
|
||||
name: 'quote',
|
||||
label: 'Quote',
|
||||
type: 'textarea',
|
||||
height: 100,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
@@ -29,3 +30,5 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default Quote;
|
||||
@@ -1,5 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
const Sidebar = () => <div className="sidebar">fake sidebar</div>
|
||||
|
||||
export default Sidebar;
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '../../../../../../../admin/styles';
|
||||
@import '../../../../../../../scss/vars.scss';
|
||||
|
||||
.button-rich-text-button {
|
||||
.btn {
|
||||
@@ -6,18 +6,22 @@
|
||||
}
|
||||
|
||||
&__modal {
|
||||
@include blur-bg;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
&.payload__modal-item--enterDone {
|
||||
@include blur-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
width: 100%;
|
||||
margin-bottom: $baseline;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
h4 {
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
import React, { Fragment, useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, useModal } from '@faceless-ui/modal';
|
||||
import { Transforms } from 'slate';
|
||||
import { useSlate } from 'slate-react';
|
||||
import { MinimalTemplate } from '../../../../../../../admin/components';
|
||||
import { ElementButton } from '../../../../../../../admin/rich-text';
|
||||
import { X } from '../../../../../../../admin/icons';
|
||||
import { Button } from '../../../../../../../admin/elements';
|
||||
import { Form, Text, Checkbox, Select, Submit, reduceFieldsToValues } from '../../../../../../../admin/forms';
|
||||
import MinimalTemplate from '../../../../../../../src/admin/components/templates/Minimal';
|
||||
import { ElementButton } from '../../../../../../../components/rich-text';
|
||||
import X from '../../../../../../../src/admin/components/icons/X';
|
||||
import Button from '../../../../../../../src/admin/components/elements/Button';
|
||||
import { Form, Text, Checkbox, Select, Submit, reduceFieldsToValues } from '../../../../../../../components/forms';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const modalSlug = 'add-button';
|
||||
|
||||
const baseClass = 'button-rich-text-button';
|
||||
|
||||
const insertButton = (editor, { url, label, style, newTab = false }) => {
|
||||
const text = { text: label };
|
||||
const initialFormData = {
|
||||
style: 'primary',
|
||||
};
|
||||
|
||||
const insertButton = (editor, { href, label, style, newTab = false }) => {
|
||||
const text = { text: ' ' };
|
||||
const button = {
|
||||
type: 'button',
|
||||
url,
|
||||
href,
|
||||
style,
|
||||
newTab,
|
||||
label,
|
||||
children: [
|
||||
text,
|
||||
],
|
||||
};
|
||||
|
||||
Transforms.insertNodes(editor, button);
|
||||
const nodes = [button, { children: [{ text: '' }] }];
|
||||
|
||||
Transforms.insertNodes(editor, nodes);
|
||||
};
|
||||
|
||||
const ButtonButton = () => {
|
||||
const ToolbarButton: React.FC = ({ path }) => {
|
||||
const { open, closeAll } = useModal();
|
||||
const editor = useSlate();
|
||||
|
||||
@@ -39,6 +45,8 @@ const ButtonButton = () => {
|
||||
closeAll();
|
||||
}, [editor, closeAll]);
|
||||
|
||||
const modalSlug = `${path}-add-button`;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<ElementButton
|
||||
@@ -62,7 +70,10 @@ const ButtonButton = () => {
|
||||
<X />
|
||||
</Button>
|
||||
</header>
|
||||
<Form onSubmit={handleAddButton}>
|
||||
<Form
|
||||
onSubmit={handleAddButton}
|
||||
initialData={initialFormData}
|
||||
>
|
||||
<Text
|
||||
label="Label"
|
||||
name="label"
|
||||
@@ -70,7 +81,7 @@ const ButtonButton = () => {
|
||||
/>
|
||||
<Text
|
||||
label="URL"
|
||||
name="URL"
|
||||
name="href"
|
||||
required
|
||||
/>
|
||||
<Select
|
||||
@@ -101,4 +112,8 @@ const ButtonButton = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default ButtonButton;
|
||||
ToolbarButton.propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default ToolbarButton;
|
||||
@@ -1,9 +1,12 @@
|
||||
@import '../../../../../../../admin/styles.scss';
|
||||
@import '../../../../../../../scss/vars.scss';
|
||||
|
||||
.rich-text-button {
|
||||
margin: $baseline 0;
|
||||
}
|
||||
|
||||
.rich-text-button__button {
|
||||
padding: base(.5) base(1.5);
|
||||
border-radius: $style-radius-s;
|
||||
display: inline-flex;
|
||||
|
||||
&--primary {
|
||||
background-color: $color-dark-gray;
|
||||
|
||||
@@ -5,20 +5,25 @@ import './index.scss';
|
||||
|
||||
const baseClass = 'rich-text-button';
|
||||
|
||||
const ButtonElement = ({ attributes, children, element }) => {
|
||||
const { label, style = 'primary' } = element;
|
||||
const ButtonElement: React.FC = ({ attributes, children, element }) => {
|
||||
const { style = 'primary', label } = element;
|
||||
|
||||
return (
|
||||
<span
|
||||
{...attributes}
|
||||
className={[
|
||||
baseClass,
|
||||
`${baseClass}--${style}`,
|
||||
].join(' ')}
|
||||
<div
|
||||
className={baseClass}
|
||||
contentEditable={false}
|
||||
>
|
||||
{label}
|
||||
{children}
|
||||
</span>
|
||||
<span
|
||||
{...attributes}
|
||||
className={[
|
||||
`${baseClass}__button`,
|
||||
`${baseClass}__button--${style}`,
|
||||
].join(' ')}
|
||||
>
|
||||
{label}
|
||||
{children}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
const button = require('./Button');
|
||||
const element = require('./Element');
|
||||
const plugin = require('./plugin');
|
||||
|
||||
module.exports = {
|
||||
name: 'button',
|
||||
button,
|
||||
element,
|
||||
plugin,
|
||||
};
|
||||
12
demo/client/components/richText/elements/Button/index.ts
Normal file
12
demo/client/components/richText/elements/Button/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import Button from './Button';
|
||||
import Element from './Element';
|
||||
import plugin from './plugin';
|
||||
|
||||
export default {
|
||||
name: 'button',
|
||||
Button,
|
||||
Element,
|
||||
plugins: [
|
||||
plugin,
|
||||
],
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
const withButton = (incomingEditor) => {
|
||||
import { Editor } from 'slate';
|
||||
|
||||
const withButton = (incomingEditor: Editor): Editor => {
|
||||
const editor = incomingEditor;
|
||||
const { isVoid } = editor;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { LeafButton } from '../../../../../../../admin/rich-text';
|
||||
import { LeafButton } from '../../../../../../../components/rich-text';
|
||||
|
||||
const Button = () => (
|
||||
<LeafButton format="purple-background">
|
||||
@@ -1,8 +0,0 @@
|
||||
const button = require('./Button');
|
||||
const leaf = require('./Leaf');
|
||||
|
||||
module.exports = {
|
||||
name: 'purple-background',
|
||||
button,
|
||||
leaf,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import Button from './Button';
|
||||
import Leaf from './Leaf';
|
||||
|
||||
export default {
|
||||
name: 'purple-background',
|
||||
Button,
|
||||
Leaf,
|
||||
};
|
||||
@@ -1,12 +1,13 @@
|
||||
const roles = require('../access/roles');
|
||||
const checkRole = require('../access/checkRole');
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
import roles from '../access/roles';
|
||||
import checkRole from '../access/checkRole';
|
||||
|
||||
const access = ({ req: { user } }) => {
|
||||
const result = checkRole(['admin'], user);
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
const Admin: PayloadCollectionConfig = {
|
||||
slug: 'admins',
|
||||
labels: {
|
||||
singular: 'Admin',
|
||||
@@ -20,11 +21,14 @@ module.exports = {
|
||||
admin: () => true,
|
||||
},
|
||||
auth: {
|
||||
tokenExpiration: 7200,
|
||||
emailVerification: false,
|
||||
tokenExpiration: 7200, // 2 hours
|
||||
verify: false,
|
||||
maxLoginAttempts: 5,
|
||||
lockTime: 600 * 1000, // lock time in ms
|
||||
useAPIKey: true,
|
||||
depth: 0,
|
||||
cookies: {
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
secure: false,
|
||||
sameSite: 'Lax',
|
||||
domain: undefined,
|
||||
},
|
||||
@@ -42,6 +46,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
name: 'apiKey',
|
||||
type: 'text',
|
||||
access: {
|
||||
read: ({ req: { user } }) => {
|
||||
if (checkRole(['admin'], user)) {
|
||||
@@ -64,3 +69,5 @@ module.exports = {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
};
|
||||
|
||||
export default Admin;
|
||||
@@ -1,15 +1,16 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
const Email = require('../blocks/Email');
|
||||
const Quote = require('../blocks/Quote');
|
||||
const NumberBlock = require('../blocks/Number');
|
||||
const CallToAction = require('../blocks/CallToAction');
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
import checkRole from '../access/checkRole';
|
||||
import Email from '../blocks/Email';
|
||||
import Quote from '../blocks/Quote';
|
||||
import NumberBlock from '../blocks/Number';
|
||||
import CallToAction from '../blocks/CallToAction';
|
||||
|
||||
const AllFields = {
|
||||
const AllFields: PayloadCollectionConfig = {
|
||||
slug: 'all-fields',
|
||||
labels: {
|
||||
singular: 'All Fields',
|
||||
plural: 'All Fields',
|
||||
},
|
||||
// labels: {
|
||||
// singular: 'All Fields',
|
||||
// plural: 'All Fields',
|
||||
// },
|
||||
admin: {
|
||||
useAsTitle: 'text',
|
||||
},
|
||||
@@ -100,6 +101,9 @@ const AllFields = {
|
||||
}],
|
||||
defaultValue: 'option-2',
|
||||
required: true,
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'row',
|
||||
@@ -190,7 +194,6 @@ const AllFields = {
|
||||
label: 'Blocks Content',
|
||||
name: 'blocks',
|
||||
minRows: 2,
|
||||
singularLabel: 'Block',
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
localized: true,
|
||||
required: true,
|
||||
@@ -238,8 +241,34 @@ const AllFields = {
|
||||
position: 'sidebar',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'richText',
|
||||
type: 'richText',
|
||||
label: 'Rich Text',
|
||||
required: true,
|
||||
admin: {
|
||||
elements: [
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'blockquote',
|
||||
'ul',
|
||||
'ol',
|
||||
'link',
|
||||
],
|
||||
leaves: [
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'strikethrough',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
module.exports = AllFields;
|
||||
export default AllFields;
|
||||
12
demo/collections/AutoLabel.ts
Normal file
12
demo/collections/AutoLabel.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const AutoLabel: PayloadCollectionConfig = {
|
||||
slug: 'auto-label',
|
||||
fields: [{
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
label: 'Text',
|
||||
}],
|
||||
};
|
||||
|
||||
export default AutoLabel;
|
||||
@@ -1,26 +0,0 @@
|
||||
const Email = require('../blocks/Email');
|
||||
const Quote = require('../blocks/Quote');
|
||||
const NumberBlock = require('../blocks/Number');
|
||||
const CallToAction = require('../blocks/CallToAction');
|
||||
|
||||
module.exports = {
|
||||
slug: 'blocks',
|
||||
labels: {
|
||||
singular: 'Blocks',
|
||||
plural: 'Blocks',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'layout',
|
||||
label: 'Layout Blocks',
|
||||
singularLabel: 'Block',
|
||||
type: 'blocks',
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
localized: true,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
43
demo/collections/Blocks.ts
Normal file
43
demo/collections/Blocks.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
import Email from '../blocks/Email';
|
||||
import Quote from '../blocks/Quote';
|
||||
import NumberBlock from '../blocks/Number';
|
||||
import CallToAction from '../blocks/CallToAction';
|
||||
|
||||
const Blocks: PayloadCollectionConfig = {
|
||||
slug: 'blocks',
|
||||
labels: {
|
||||
singular: 'Blocks',
|
||||
plural: 'Blocks',
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'layout',
|
||||
label: 'Layout Blocks',
|
||||
labels: {
|
||||
singular: 'Block',
|
||||
plural: 'Blocks',
|
||||
},
|
||||
type: 'blocks',
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
localized: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'nonLocalizedLayout',
|
||||
label: 'Non Localized Layout',
|
||||
labels: {
|
||||
singular: 'Layout',
|
||||
plural: 'Layouts',
|
||||
},
|
||||
type: 'blocks',
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default Blocks;
|
||||
@@ -1,4 +1,6 @@
|
||||
const Code = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const Code: PayloadCollectionConfig = {
|
||||
slug: 'code',
|
||||
labels: {
|
||||
singular: 'Code',
|
||||
@@ -17,4 +19,4 @@ const Code = {
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = Code;
|
||||
export default Code;
|
||||
@@ -1,4 +1,6 @@
|
||||
const Conditions = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const Conditions: PayloadCollectionConfig = {
|
||||
slug: 'conditions',
|
||||
labels: {
|
||||
singular: 'Conditions',
|
||||
@@ -50,4 +52,4 @@ const Conditions = {
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = Conditions;
|
||||
export default Conditions;
|
||||
@@ -1,5 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
const Description = () => <div className="description">fake description field</div>
|
||||
|
||||
export default Description;
|
||||
@@ -0,0 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
const Description: React.FC = () => <div className="description">fake description field</div>;
|
||||
|
||||
export default Description;
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Props } from './types';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const Filter = ({ onChange, value }) => (
|
||||
const Filter: React.FC<Props> = ({ onChange, value }) => (
|
||||
<input
|
||||
className="custom-description-filter"
|
||||
type="text"
|
||||
@@ -12,13 +12,4 @@ const Filter = ({ onChange, value }) => (
|
||||
/>
|
||||
);
|
||||
|
||||
Filter.defaultProps = {
|
||||
value: '',
|
||||
};
|
||||
|
||||
Filter.propTypes = {
|
||||
onChange: PropTypes.func.isRequired,
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Filter;
|
||||
@@ -0,0 +1,4 @@
|
||||
export type Props = {
|
||||
value?: string
|
||||
onChange: (value: string) => void
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Group } from '../../../../../../../field-types';
|
||||
import { Group } from '../../../../../../../components/forms';
|
||||
|
||||
const CustomGroup = (props) => {
|
||||
return (
|
||||
<div className="custom-group">
|
||||
<Group {...props} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const CustomGroup: React.FC = (props) => (
|
||||
<div className="custom-group">
|
||||
<Group {...props} />
|
||||
</div>
|
||||
);
|
||||
|
||||
CustomGroup.defaultProps = {
|
||||
value: '',
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DefaultList from '../../../../../../src/client/components/views/collections/List/Default';
|
||||
import DefaultList from '../../../../../../src/admin/components/views/collections/List/Default';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
const DescriptionField = require('./components/fields/Description/Field');
|
||||
const DescriptionCell = require('./components/fields/Description/Cell');
|
||||
const DescriptionFilter = require('./components/fields/Description/Filter');
|
||||
const NestedArrayField = require('./components/fields/NestedArrayCustomField/Field');
|
||||
const GroupField = require('./components/fields/Group/Field');
|
||||
const NestedGroupField = require('./components/fields/NestedGroupCustomField/Field');
|
||||
const NestedText1Field = require('./components/fields/NestedText1/Field');
|
||||
const ListView = require('./components/views/List');
|
||||
import { PayloadCollectionConfig } from '../../../src/collections/config/types';
|
||||
import DescriptionField from './components/fields/Description/Field';
|
||||
import DescriptionCell from './components/fields/Description/Cell';
|
||||
import DescriptionFilter from './components/fields/Description/Filter';
|
||||
import NestedArrayField from './components/fields/NestedArrayCustomField/Field';
|
||||
import GroupField from './components/fields/Group/Field';
|
||||
import NestedGroupField from './components/fields/NestedGroupCustomField/Field';
|
||||
import NestedText1Field from './components/fields/NestedText1/Field';
|
||||
import ListView from './components/views/List';
|
||||
|
||||
module.exports = {
|
||||
const CustomComponents: PayloadCollectionConfig = {
|
||||
slug: 'custom-components',
|
||||
labels: {
|
||||
singular: 'Custom Component',
|
||||
@@ -27,14 +28,13 @@ module.exports = {
|
||||
name: 'description',
|
||||
label: 'Description',
|
||||
type: 'textarea',
|
||||
height: 100,
|
||||
required: true,
|
||||
localized: true,
|
||||
admin: {
|
||||
components: {
|
||||
field: DescriptionField,
|
||||
cell: DescriptionCell,
|
||||
filter: DescriptionFilter,
|
||||
Field: DescriptionField,
|
||||
Cell: DescriptionCell,
|
||||
Filter: DescriptionFilter,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -49,7 +49,7 @@ module.exports = {
|
||||
label: 'Nested Array Custom Field',
|
||||
admin: {
|
||||
components: {
|
||||
field: NestedArrayField,
|
||||
Field: NestedArrayField,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -61,7 +61,7 @@ module.exports = {
|
||||
type: 'group',
|
||||
admin: {
|
||||
components: {
|
||||
field: GroupField,
|
||||
Field: GroupField,
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
@@ -71,7 +71,7 @@ module.exports = {
|
||||
label: 'Nested Group Custom Field',
|
||||
admin: {
|
||||
components: {
|
||||
field: NestedGroupField,
|
||||
Field: NestedGroupField,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -86,7 +86,7 @@ module.exports = {
|
||||
type: 'text',
|
||||
admin: {
|
||||
components: {
|
||||
field: NestedText1Field,
|
||||
Field: NestedText1Field,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
@@ -101,9 +101,9 @@ module.exports = {
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
components: {
|
||||
views: {
|
||||
List: ListView,
|
||||
},
|
||||
List: ListView,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default CustomComponents;
|
||||
293
demo/collections/DefaultValues.ts
Normal file
293
demo/collections/DefaultValues.ts
Normal file
@@ -0,0 +1,293 @@
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
import checkRole from '../access/checkRole';
|
||||
import Email from '../blocks/Email';
|
||||
import Quote from '../blocks/Quote';
|
||||
import NumberBlock from '../blocks/Number';
|
||||
import CallToAction from '../blocks/CallToAction';
|
||||
|
||||
const DefaultValues: PayloadCollectionConfig = {
|
||||
slug: 'default-values',
|
||||
labels: {
|
||||
singular: 'Default Value Test',
|
||||
plural: 'Default Value Tests',
|
||||
},
|
||||
admin: {
|
||||
useAsTitle: 'text',
|
||||
},
|
||||
preview: (doc, token) => {
|
||||
if (doc && doc.text) {
|
||||
return `http://localhost:3000/previewable-posts/${doc.text.value}?preview=true&token=${token}`;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
label: 'Text',
|
||||
defaultValue: 'Default Value',
|
||||
unique: true,
|
||||
access: {
|
||||
create: ({ req: { user } }) => checkRole(['admin'], user),
|
||||
update: ({ req: { user } }) => checkRole(['admin'], user),
|
||||
read: ({ req: { user } }) => Boolean(user),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
label: 'Image',
|
||||
relationTo: 'media',
|
||||
},
|
||||
{
|
||||
name: 'select',
|
||||
label: 'Select',
|
||||
type: 'select',
|
||||
options: [{
|
||||
value: 'option-1',
|
||||
label: 'Option 1 Label',
|
||||
}, {
|
||||
value: 'option-2',
|
||||
label: 'Option 2 Label',
|
||||
}, {
|
||||
value: 'option-3',
|
||||
label: 'Option 3 Label',
|
||||
}, {
|
||||
value: 'option-4',
|
||||
label: 'Option 4 Label',
|
||||
}],
|
||||
defaultValue: 'option-1',
|
||||
},
|
||||
{
|
||||
name: 'selectMany',
|
||||
label: 'Select w/ hasMany',
|
||||
type: 'select',
|
||||
options: [{
|
||||
value: 'option-1',
|
||||
label: 'Option 1 Label',
|
||||
}, {
|
||||
value: 'option-2',
|
||||
label: 'Option 2 Label',
|
||||
}, {
|
||||
value: 'option-3',
|
||||
label: 'Option 3 Label',
|
||||
}, {
|
||||
value: 'option-4',
|
||||
label: 'Option 4 Label',
|
||||
}],
|
||||
defaultValue: ['option-1', 'option-4'],
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
name: 'radioGroupExample',
|
||||
label: 'Radio Group Example',
|
||||
type: 'radio',
|
||||
options: [{
|
||||
value: 'option-1',
|
||||
label: 'Options 1 Label',
|
||||
}, {
|
||||
value: 'option-2',
|
||||
label: 'Option 2 Label',
|
||||
}, {
|
||||
value: 'option-3',
|
||||
label: 'Option 3 Label',
|
||||
}],
|
||||
defaultValue: 'option-2',
|
||||
},
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
name: 'email',
|
||||
label: 'Email',
|
||||
type: 'email',
|
||||
defaultValue: 'some@email.com',
|
||||
}, {
|
||||
name: 'number',
|
||||
label: 'Number',
|
||||
type: 'number',
|
||||
defaultValue: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'group',
|
||||
label: 'Group',
|
||||
name: 'group',
|
||||
defaultValue: {
|
||||
nestedText1: 'neat',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
name: 'nestedText1',
|
||||
label: 'Nested Text 1',
|
||||
type: 'text',
|
||||
defaultValue: 'nested default text 1',
|
||||
}, {
|
||||
name: 'nestedText2',
|
||||
label: 'Nested Text 2',
|
||||
type: 'text',
|
||||
defaultValue: 'nested default text 2',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'array',
|
||||
label: 'Array',
|
||||
name: 'array',
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
defaultValue: [
|
||||
{
|
||||
arrayText1: 'Get out',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
name: 'arrayText1',
|
||||
label: 'Array Text 1',
|
||||
type: 'text',
|
||||
admin: {
|
||||
width: '50%',
|
||||
},
|
||||
defaultValue: 'default array text',
|
||||
},
|
||||
{
|
||||
name: 'arrayText2',
|
||||
label: 'Array Text 2',
|
||||
type: 'text',
|
||||
admin: {
|
||||
width: '50%',
|
||||
},
|
||||
access: {
|
||||
read: ({ req: { user } }) => Boolean(user),
|
||||
update: ({ req: { user } }) => checkRole(['admin'], user),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'arrayText3',
|
||||
label: 'Array Text 3',
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'checkbox',
|
||||
label: 'Checkbox',
|
||||
type: 'checkbox',
|
||||
defaultValue: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'blocks',
|
||||
label: 'Blocks Content',
|
||||
name: 'blocks',
|
||||
labels: {
|
||||
singular: 'Block',
|
||||
plural: 'Blocks',
|
||||
},
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
localized: true,
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
defaultValue: [
|
||||
{
|
||||
blockType: 'email',
|
||||
testEmail: 'dev@payloadcms.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'relationship',
|
||||
label: 'Relationship to One Collection',
|
||||
name: 'relationship',
|
||||
relationTo: 'conditions',
|
||||
},
|
||||
{
|
||||
type: 'relationship',
|
||||
label: 'Relationship hasMany',
|
||||
name: 'relationshipHasMany',
|
||||
relationTo: 'localized-posts',
|
||||
hasMany: true,
|
||||
},
|
||||
{
|
||||
type: 'relationship',
|
||||
label: 'Relationship to Multiple Collections',
|
||||
name: 'relationshipMultipleCollections',
|
||||
relationTo: ['localized-posts', 'conditions'],
|
||||
},
|
||||
{
|
||||
type: 'textarea',
|
||||
label: 'Textarea',
|
||||
name: 'textarea',
|
||||
defaultValue: 'my textarea text',
|
||||
},
|
||||
{
|
||||
name: 'slug',
|
||||
type: 'text',
|
||||
label: 'Slug',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
},
|
||||
localized: true,
|
||||
unique: true,
|
||||
defaultValue: 'my-slug',
|
||||
},
|
||||
{
|
||||
name: 'checkbox',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox',
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
},
|
||||
defaultValue: true,
|
||||
},
|
||||
{
|
||||
name: 'richText',
|
||||
type: 'richText',
|
||||
label: 'Rich Text',
|
||||
admin: {
|
||||
elements: [
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'blockquote',
|
||||
'ul',
|
||||
'ol',
|
||||
'link',
|
||||
],
|
||||
leaves: [
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'strikethrough',
|
||||
],
|
||||
},
|
||||
defaultValue: [{
|
||||
children: [{ text: 'Cookin now' }],
|
||||
}],
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
export default DefaultValues;
|
||||
@@ -1,4 +1,5 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
import checkRole from '../access/checkRole';
|
||||
|
||||
const access = ({ req: { user } }) => {
|
||||
const isAdmin = checkRole(['admin'], user);
|
||||
@@ -18,7 +19,7 @@ const access = ({ req: { user } }) => {
|
||||
return false;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
const Files: PayloadCollectionConfig = {
|
||||
slug: 'files',
|
||||
labels: {
|
||||
singular: 'File',
|
||||
@@ -65,3 +66,5 @@ module.exports = {
|
||||
useAsTitle: 'filename',
|
||||
},
|
||||
};
|
||||
|
||||
export default Files;
|
||||
@@ -1,4 +1,6 @@
|
||||
const HiddenFields = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const HiddenFields: PayloadCollectionConfig = {
|
||||
slug: 'hidden-fields',
|
||||
labels: {
|
||||
singular: 'Hidden Fields',
|
||||
@@ -15,7 +17,9 @@ const HiddenFields = {
|
||||
name: 'hiddenAdmin',
|
||||
type: 'text',
|
||||
label: 'Hidden on Admin',
|
||||
hidden: 'admin',
|
||||
admin: {
|
||||
hidden: true,
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
@@ -28,4 +32,4 @@ const HiddenFields = {
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = HiddenFields;
|
||||
export default HiddenFields;
|
||||
@@ -1,5 +1,8 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
module.exports = {
|
||||
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const Hooks: PayloadCollectionConfig = {
|
||||
slug: 'hooks',
|
||||
labels: {
|
||||
singular: 'Hook',
|
||||
@@ -82,10 +85,11 @@ module.exports = {
|
||||
name: 'description',
|
||||
label: 'Description',
|
||||
type: 'textarea',
|
||||
height: 100,
|
||||
required: true,
|
||||
localized: true,
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default Hooks;
|
||||
@@ -1,4 +1,6 @@
|
||||
const LocalOperations = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const LocalOperations: PayloadCollectionConfig = {
|
||||
slug: 'local-operations',
|
||||
labels: {
|
||||
singular: 'Local Operation',
|
||||
@@ -33,4 +35,4 @@ const LocalOperations = {
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = LocalOperations;
|
||||
export default LocalOperations;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const LocalizedPosts: PayloadCollectionConfig = {
|
||||
slug: 'localized-posts',
|
||||
labels: {
|
||||
singular: 'Localized Post',
|
||||
@@ -11,6 +13,7 @@ module.exports = {
|
||||
'priority',
|
||||
'createdAt',
|
||||
],
|
||||
enableRichTextRelationship: true,
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
@@ -42,7 +45,6 @@ module.exports = {
|
||||
name: 'description',
|
||||
label: 'Description',
|
||||
type: 'textarea',
|
||||
height: 100,
|
||||
required: true,
|
||||
localized: true,
|
||||
},
|
||||
@@ -56,3 +58,5 @@ module.exports = {
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default LocalizedPosts;
|
||||
@@ -1,4 +1,6 @@
|
||||
const LocalizedArrays = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const LocalizedArrays: PayloadCollectionConfig = {
|
||||
slug: 'localized-arrays',
|
||||
labels: {
|
||||
singular: 'Localized Array',
|
||||
@@ -47,4 +49,4 @@ const LocalizedArrays = {
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
module.exports = LocalizedArrays;
|
||||
export default LocalizedArrays;
|
||||
@@ -1,7 +1,6 @@
|
||||
const path = require('path');
|
||||
const checkRole = require('../access/checkRole');
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
module.exports = {
|
||||
const Media: PayloadCollectionConfig = {
|
||||
slug: 'media',
|
||||
labels: {
|
||||
singular: 'Media',
|
||||
@@ -10,6 +9,9 @@ module.exports = {
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
admin: {
|
||||
enableRichTextRelationship: true,
|
||||
},
|
||||
upload: {
|
||||
staticURL: '/media',
|
||||
staticDir: './media',
|
||||
@@ -41,26 +43,9 @@ module.exports = {
|
||||
type: 'text',
|
||||
required: true,
|
||||
localized: true,
|
||||
hooks: {
|
||||
afterRead: [
|
||||
({ value }) => `${value} alt`,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sizes',
|
||||
fields: [
|
||||
{
|
||||
name: 'icon',
|
||||
access: {
|
||||
read: ({ req: { user } }) => {
|
||||
const result = checkRole(['admin'], user);
|
||||
return result;
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default Media;
|
||||
@@ -1,4 +1,6 @@
|
||||
const NestedArray = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const NestedArray: PayloadCollectionConfig = {
|
||||
slug: 'nested-arrays',
|
||||
labels: {
|
||||
singular: 'Nested Array',
|
||||
@@ -23,7 +25,7 @@ const NestedArray = {
|
||||
{
|
||||
name: 'parentIdentifier',
|
||||
label: 'Parent Identifier',
|
||||
defaultValue: '',
|
||||
defaultValue: ' ',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
@@ -67,4 +69,4 @@ const NestedArray = {
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
module.exports = NestedArray;
|
||||
export default NestedArray;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const Preview: PayloadCollectionConfig = {
|
||||
slug: 'previewable-post',
|
||||
labels: {
|
||||
singular: 'Previewable Post',
|
||||
@@ -27,3 +29,5 @@ module.exports = {
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default Preview;
|
||||
@@ -1,8 +1,9 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
import checkRole from '../access/checkRole';
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const access = ({ req: { user } }) => checkRole(['admin'], user);
|
||||
|
||||
module.exports = {
|
||||
const PublicUsers: PayloadCollectionConfig = {
|
||||
slug: 'public-users',
|
||||
labels: {
|
||||
singular: 'Public User',
|
||||
@@ -32,8 +33,9 @@ module.exports = {
|
||||
},
|
||||
auth: {
|
||||
tokenExpiration: 300,
|
||||
emailVerification: true,
|
||||
generateVerificationUrl: (req, token) => `http://localhost:3000/api/verify?token=${token}`,
|
||||
verify: true,
|
||||
maxLoginAttempts: 5,
|
||||
lockTime: 600 * 1000, // lock time in ms
|
||||
cookies: {
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'Lax',
|
||||
@@ -55,3 +57,5 @@ module.exports = {
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default PublicUsers;
|
||||
@@ -1,20 +0,0 @@
|
||||
module.exports = {
|
||||
slug: 'relationship-a',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
labels: {
|
||||
singular: 'Relationship A',
|
||||
plural: 'Relationship A',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'post',
|
||||
label: 'Post',
|
||||
type: 'relationship',
|
||||
relationTo: 'relationship-b',
|
||||
localized: false,
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
40
demo/collections/RelationshipA.ts
Normal file
40
demo/collections/RelationshipA.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const RelationshipA: PayloadCollectionConfig = {
|
||||
slug: 'relationship-a',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
labels: {
|
||||
singular: 'Relationship A',
|
||||
plural: 'Relationship A',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'post',
|
||||
label: 'Post',
|
||||
type: 'relationship',
|
||||
relationTo: 'relationship-b',
|
||||
localized: true,
|
||||
},
|
||||
// {
|
||||
// name: 'LocalizedPost',
|
||||
// label: 'Localized Post',
|
||||
// type: 'relationship',
|
||||
// relationTo: 'localized-posts',
|
||||
// hasMany: true,
|
||||
// localized: true,
|
||||
// },
|
||||
{
|
||||
name: 'postLocalizedMultiple',
|
||||
label: 'Localized Post Multiple',
|
||||
type: 'relationship',
|
||||
relationTo: ['localized-posts', 'all-fields'],
|
||||
hasMany: true,
|
||||
localized: true,
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default RelationshipA;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const RelationshipB: PayloadCollectionConfig = {
|
||||
slug: 'relationship-b',
|
||||
access: {
|
||||
read: () => true,
|
||||
@@ -19,3 +21,5 @@ module.exports = {
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default RelationshipB;
|
||||
@@ -1,42 +0,0 @@
|
||||
const Button = require('../client/components/richText/elements/Button');
|
||||
const PurpleBackground = require('../client/components/richText/leaves/PurpleBackground');
|
||||
|
||||
const RichText = {
|
||||
slug: 'rich-text',
|
||||
labels: {
|
||||
singular: 'Rich Text',
|
||||
plural: 'Rich Texts',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'richText',
|
||||
type: 'richText',
|
||||
label: 'Rich Text',
|
||||
required: true,
|
||||
admin: {
|
||||
elements: [
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
// 'blockquote',
|
||||
Button,
|
||||
'ul',
|
||||
'ol',
|
||||
'link',
|
||||
],
|
||||
leaves: [
|
||||
'bold',
|
||||
'italic',
|
||||
PurpleBackground,
|
||||
// 'underline',
|
||||
// 'strikethrough',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = RichText;
|
||||
38
demo/collections/RichText.ts
Normal file
38
demo/collections/RichText.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import Button from '../client/components/richText/elements/Button';
|
||||
import PurpleBackground from '../client/components/richText/leaves/PurpleBackground';
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const RichText: PayloadCollectionConfig = {
|
||||
slug: 'rich-text',
|
||||
labels: {
|
||||
singular: 'Rich Text',
|
||||
plural: 'Rich Texts',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'defaultRichText',
|
||||
type: 'richText',
|
||||
label: 'Default Rich Text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'customRichText',
|
||||
type: 'richText',
|
||||
label: 'Customized Rich Text',
|
||||
required: true,
|
||||
admin: {
|
||||
elements: [
|
||||
'h2',
|
||||
'h3',
|
||||
Button,
|
||||
],
|
||||
leaves: [
|
||||
'bold',
|
||||
PurpleBackground,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default RichText;
|
||||
@@ -1,4 +1,6 @@
|
||||
const Select = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const Select: PayloadCollectionConfig = {
|
||||
slug: 'select',
|
||||
labels: {
|
||||
singular: 'Select',
|
||||
@@ -40,4 +42,4 @@ const Select = {
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = Select;
|
||||
export default Select;
|
||||
@@ -1,6 +1,7 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
import checkRole from '../access/checkRole';
|
||||
|
||||
module.exports = {
|
||||
const StrictAccess: PayloadCollectionConfig = {
|
||||
slug: 'strict-access',
|
||||
labels: {
|
||||
singular: 'Strict Access',
|
||||
@@ -71,3 +72,5 @@ module.exports = {
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default StrictAccess;
|
||||
@@ -1,4 +1,6 @@
|
||||
module.exports = {
|
||||
import { PayloadCollectionConfig } from '../../src/collections/config/types';
|
||||
|
||||
const Validations: PayloadCollectionConfig = {
|
||||
slug: 'validations',
|
||||
labels: {
|
||||
singular: 'Validation',
|
||||
@@ -106,5 +108,6 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
|
||||
export default Validations;
|
||||
@@ -1,8 +1,9 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
const Quote = require('../blocks/Quote');
|
||||
const CallToAction = require('../blocks/CallToAction');
|
||||
import checkRole from '../access/checkRole';
|
||||
import Quote from '../blocks/Quote';
|
||||
import CallToAction from '../blocks/CallToAction';
|
||||
import { PayloadGlobalConfig } from '../../src/globals/config/types';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
slug: 'blocks-global',
|
||||
label: 'Blocks Global',
|
||||
access: {
|
||||
@@ -18,4 +19,4 @@ module.exports = {
|
||||
localized: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
} as PayloadGlobalConfig;
|
||||
@@ -1,6 +1,7 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
import { PayloadGlobalConfig } from '../../src/globals/config/types';
|
||||
import checkRole from '../access/checkRole';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
slug: 'global-with-access',
|
||||
label: 'Global with Strict Access',
|
||||
access: {
|
||||
@@ -31,4 +32,4 @@ module.exports = {
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
} as PayloadGlobalConfig;
|
||||
@@ -1,6 +1,7 @@
|
||||
const checkRole = require('../access/checkRole');
|
||||
import { PayloadGlobalConfig } from '../../src/globals/config/types';
|
||||
import checkRole from '../access/checkRole';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
slug: 'navigation-array',
|
||||
label: 'Navigation Array',
|
||||
access: {
|
||||
@@ -24,4 +25,4 @@ module.exports = {
|
||||
}],
|
||||
},
|
||||
],
|
||||
};
|
||||
} as PayloadGlobalConfig;
|
||||
14
demo/index.js
Normal file
14
demo/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const babelConfig = require('../babel.config');
|
||||
|
||||
require('@babel/register')({
|
||||
...babelConfig,
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
||||
env: {
|
||||
development: {
|
||||
sourceMaps: 'inline',
|
||||
retainLines: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
require('./server.ts');
|
||||
@@ -1,119 +0,0 @@
|
||||
const Admin = require('./collections/Admin');
|
||||
const AllFields = require('./collections/AllFields');
|
||||
const Code = require('./collections/Code');
|
||||
const Conditions = require('./collections/Conditions');
|
||||
const CustomComponents = require('./collections/CustomComponents');
|
||||
const File = require('./collections/File');
|
||||
const Blocks = require('./collections/Blocks');
|
||||
const HiddenFields = require('./collections/HiddenFields');
|
||||
const Hooks = require('./collections/Hooks');
|
||||
const Localized = require('./collections/Localized');
|
||||
const LocalizedArray = require('./collections/LocalizedArray');
|
||||
const LocalOperations = require('./collections/LocalOperations');
|
||||
const Media = require('./collections/Media');
|
||||
const NestedArrays = require('./collections/NestedArrays');
|
||||
const Preview = require('./collections/Preview');
|
||||
const PublicUsers = require('./collections/PublicUsers');
|
||||
const RelationshipA = require('./collections/RelationshipA');
|
||||
const RelationshipB = require('./collections/RelationshipB');
|
||||
const RichText = require('./collections/RichText');
|
||||
const Select = require('./collections/Select');
|
||||
const StrictPolicies = require('./collections/StrictPolicies');
|
||||
const Validations = require('./collections/Validations');
|
||||
|
||||
const BlocksGlobal = require('./globals/BlocksGlobal');
|
||||
const NavigationArray = require('./globals/NavigationArray');
|
||||
const GlobalWithStrictAccess = require('./globals/GlobalWithStrictAccess');
|
||||
|
||||
module.exports = {
|
||||
admin: {
|
||||
user: 'admins',
|
||||
// indexHTML: 'custom-index.html',
|
||||
meta: {
|
||||
titleSuffix: '- Payload Demo',
|
||||
// ogImage: '/static/find-image-here.jpg',
|
||||
// favicon: '/img/whatever.png',
|
||||
},
|
||||
disable: false,
|
||||
components: {
|
||||
// nav: () => (
|
||||
// <div>Hello</div>
|
||||
// ),
|
||||
},
|
||||
},
|
||||
email: {
|
||||
fromName: 'Payload',
|
||||
fromAddress: 'hello@payloadcms.com',
|
||||
},
|
||||
collections: [
|
||||
Admin,
|
||||
AllFields,
|
||||
Code,
|
||||
Conditions,
|
||||
CustomComponents,
|
||||
File,
|
||||
Blocks,
|
||||
HiddenFields,
|
||||
Hooks,
|
||||
Localized,
|
||||
LocalizedArray,
|
||||
LocalOperations,
|
||||
Media,
|
||||
NestedArrays,
|
||||
Preview,
|
||||
PublicUsers,
|
||||
RelationshipA,
|
||||
RelationshipB,
|
||||
RichText,
|
||||
Select,
|
||||
StrictPolicies,
|
||||
Validations,
|
||||
],
|
||||
globals: [
|
||||
NavigationArray,
|
||||
GlobalWithStrictAccess,
|
||||
BlocksGlobal,
|
||||
],
|
||||
cookiePrefix: 'payload',
|
||||
serverURL: 'http://localhost:3000',
|
||||
cors: [
|
||||
'http://localhost',
|
||||
'http://localhost:3000',
|
||||
'http://localhost:8080',
|
||||
'http://localhost:8081',
|
||||
],
|
||||
csrf: [
|
||||
'http://localhost:3000',
|
||||
'https://other-app-here.com',
|
||||
],
|
||||
routes: {
|
||||
api: '/api',
|
||||
admin: '/admin',
|
||||
graphQL: '/graphql',
|
||||
graphQLPlayground: '/graphql-playground',
|
||||
},
|
||||
defaultDepth: 2,
|
||||
compression: {},
|
||||
paths: {
|
||||
scss: 'client/scss/overrides.scss',
|
||||
},
|
||||
graphQL: {
|
||||
mutations: {},
|
||||
queries: {},
|
||||
},
|
||||
localization: {
|
||||
locales: [
|
||||
'en',
|
||||
'es',
|
||||
],
|
||||
defaultLocale: 'en',
|
||||
fallback: true,
|
||||
},
|
||||
productionGraphQLPlayground: false,
|
||||
hooks: {
|
||||
afterError: () => {
|
||||
console.error('global error config handler');
|
||||
},
|
||||
},
|
||||
webpack: (config) => config,
|
||||
};
|
||||
140
demo/payload.config.ts
Normal file
140
demo/payload.config.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import path from 'path';
|
||||
import { buildConfig } from '../src/config/build';
|
||||
|
||||
import Admin from './collections/Admin';
|
||||
import AllFields from './collections/AllFields';
|
||||
import AutoLabel from './collections/AutoLabel';
|
||||
import Code from './collections/Code';
|
||||
import Conditions from './collections/Conditions';
|
||||
import CustomComponents from './collections/CustomComponents';
|
||||
import File from './collections/File';
|
||||
import Blocks from './collections/Blocks';
|
||||
import DefaultValues from './collections/DefaultValues';
|
||||
import HiddenFields from './collections/HiddenFields';
|
||||
import Hooks from './collections/Hooks';
|
||||
import Localized from './collections/Localized';
|
||||
import LocalizedArray from './collections/LocalizedArray';
|
||||
import LocalOperations from './collections/LocalOperations';
|
||||
import Media from './collections/Media';
|
||||
import NestedArrays from './collections/NestedArrays';
|
||||
import Preview from './collections/Preview';
|
||||
import PublicUsers from './collections/PublicUsers';
|
||||
import RelationshipA from './collections/RelationshipA';
|
||||
import RelationshipB from './collections/RelationshipB';
|
||||
import RichText from './collections/RichText';
|
||||
import Select from './collections/Select';
|
||||
import StrictPolicies from './collections/StrictPolicies';
|
||||
import Validations from './collections/Validations';
|
||||
|
||||
import BlocksGlobal from './globals/BlocksGlobal';
|
||||
import NavigationArray from './globals/NavigationArray';
|
||||
import GlobalWithStrictAccess from './globals/GlobalWithStrictAccess';
|
||||
|
||||
export default buildConfig({
|
||||
cookiePrefix: 'payload',
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: 'admins',
|
||||
indexHTML: path.resolve(__dirname, './client/index.html'),
|
||||
// meta: {
|
||||
// titleSuffix: '- Payload Demo',
|
||||
// // ogImage: '/static/find-image-here.jpg',
|
||||
// // favicon: '/img/whatever.png',
|
||||
// },
|
||||
disable: false,
|
||||
components: {
|
||||
// Nav: () => (
|
||||
// <div>Hello</div>
|
||||
// ),
|
||||
},
|
||||
},
|
||||
email: {
|
||||
transport: 'mock',
|
||||
fromName: 'Payload',
|
||||
fromAddress: 'hello@payloadcms.com',
|
||||
},
|
||||
collections: [
|
||||
Admin,
|
||||
AllFields,
|
||||
AutoLabel,
|
||||
Code,
|
||||
Conditions,
|
||||
CustomComponents,
|
||||
File,
|
||||
DefaultValues,
|
||||
Blocks,
|
||||
HiddenFields,
|
||||
Hooks,
|
||||
Localized,
|
||||
LocalizedArray,
|
||||
LocalOperations,
|
||||
Media,
|
||||
NestedArrays,
|
||||
Preview,
|
||||
PublicUsers,
|
||||
RelationshipA,
|
||||
RelationshipB,
|
||||
RichText,
|
||||
Select,
|
||||
StrictPolicies,
|
||||
Validations,
|
||||
],
|
||||
globals: [
|
||||
NavigationArray,
|
||||
GlobalWithStrictAccess,
|
||||
BlocksGlobal,
|
||||
],
|
||||
cors: [
|
||||
'http://localhost',
|
||||
'http://localhost:3000',
|
||||
'http://localhost:8080',
|
||||
'http://localhost:8081',
|
||||
],
|
||||
csrf: [
|
||||
'http://localhost:3000',
|
||||
'https://other-app-here.com',
|
||||
],
|
||||
routes: {
|
||||
api: '/api',
|
||||
admin: '/admin',
|
||||
graphQL: '/graphql',
|
||||
graphQLPlayground: '/graphql-playground',
|
||||
},
|
||||
defaultDepth: 2,
|
||||
compression: {},
|
||||
paths: {
|
||||
scss: path.resolve(__dirname, './client/scss/overrides.scss'),
|
||||
},
|
||||
graphQL: {
|
||||
maxComplexity: 1000,
|
||||
mutations: {}, // TODO: needs typing
|
||||
queries: {}, // TODO: needs typing
|
||||
disablePlaygroundInProduction: true,
|
||||
},
|
||||
// rateLimit: {
|
||||
// window: 15 * 60 * 100,
|
||||
// max: 100,
|
||||
// trustProxy: true,
|
||||
// skip: (req) => req.ip === '127.0.0.1',
|
||||
// },
|
||||
maxDepth: 10,
|
||||
localization: {
|
||||
locales: [
|
||||
'en',
|
||||
'es',
|
||||
],
|
||||
defaultLocale: 'en',
|
||||
fallback: true,
|
||||
},
|
||||
hooks: {
|
||||
afterError: (err) => {
|
||||
console.error('global error config handler', err);
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
limits: {
|
||||
fileSize: 10000000, // 10MB
|
||||
},
|
||||
},
|
||||
webpack: (config) => config,
|
||||
});
|
||||
@@ -1,56 +0,0 @@
|
||||
/* eslint-disable no-console */
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const payload = require('../src');
|
||||
const logger = require('../src/utilities/logger')();
|
||||
|
||||
const expressApp = express();
|
||||
|
||||
expressApp.use('/static', express.static(path.resolve(__dirname, 'client/static')));
|
||||
|
||||
payload.init({
|
||||
email: {
|
||||
transport: 'mock',
|
||||
},
|
||||
secret: 'SECRET_KEY',
|
||||
mongoURL: 'mongodb://localhost/payload',
|
||||
express: expressApp,
|
||||
onInit: () => {
|
||||
logger.info('Payload is initialized');
|
||||
// console.log('Payload is initialized');
|
||||
},
|
||||
});
|
||||
|
||||
const externalRouter = express.Router();
|
||||
|
||||
externalRouter.use(payload.authenticate);
|
||||
|
||||
externalRouter.get('/', (req, res) => {
|
||||
if (req.user) {
|
||||
return res.send(`Authenticated successfully as ${req.user.email}.`);
|
||||
}
|
||||
|
||||
return res.send('Not authenticated');
|
||||
});
|
||||
|
||||
expressApp.use('/external-route', externalRouter);
|
||||
|
||||
exports.start = (cb) => {
|
||||
const server = expressApp.listen(3000, async () => {
|
||||
logger.info(`listening on ${3000}...`);
|
||||
|
||||
const creds = await payload.getMockEmailCredentials();
|
||||
logger.info(`Mock email account username: ${creds.user}`);
|
||||
logger.info(`Mock email account password: ${creds.pass}`);
|
||||
logger.info(`Log in to mock email provider at ${creds.web}`);
|
||||
|
||||
if (cb) cb();
|
||||
});
|
||||
|
||||
return server;
|
||||
};
|
||||
|
||||
// when server.js is launched directly
|
||||
if (module.id === require.main.id) {
|
||||
exports.start();
|
||||
}
|
||||
35
demo/server.ts
Normal file
35
demo/server.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/* eslint-disable no-console */
|
||||
import express from 'express';
|
||||
import path from 'path';
|
||||
import payload from '../src';
|
||||
|
||||
const expressApp = express();
|
||||
|
||||
expressApp.use('/static', express.static(path.resolve(__dirname, 'client/static')));
|
||||
|
||||
payload.init({
|
||||
secret: 'SECRET_KEY',
|
||||
mongoURL: 'mongodb://localhost/payload',
|
||||
express: expressApp,
|
||||
onInit: (app) => {
|
||||
app.logger.info('Payload Demo Initialized');
|
||||
},
|
||||
});
|
||||
|
||||
const externalRouter = express.Router();
|
||||
|
||||
externalRouter.use(payload.authenticate);
|
||||
|
||||
externalRouter.get('/', (req, res) => {
|
||||
if (req.user) {
|
||||
return res.send(`Authenticated successfully as ${req.user.email}.`);
|
||||
}
|
||||
|
||||
return res.send('Not authenticated');
|
||||
});
|
||||
|
||||
expressApp.use('/external-route', externalRouter);
|
||||
|
||||
expressApp.listen(3000, async () => {
|
||||
payload.logger.info(`listening on ${3000}...`);
|
||||
});
|
||||
38
docs/Access-Control/config.mdx
Normal file
38
docs/Access-Control/config.mdx
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Access Control Config
|
||||
label: Config
|
||||
order: 10
|
||||
---
|
||||
|
||||
Access can be configured at a Collection-level or field-level within your Collection configuration.
|
||||
|
||||
```js
|
||||
// Collection config
|
||||
module.exports = {
|
||||
slug: 'public-user',
|
||||
// highlight-start
|
||||
access: {
|
||||
create: () => true,
|
||||
read: () => true,
|
||||
update: () => true,
|
||||
delete: () => true,
|
||||
admin: () => true,
|
||||
},
|
||||
// highlight-end
|
||||
fields: [
|
||||
{
|
||||
name: 'lockedDownField',
|
||||
label: 'Locked Down',
|
||||
type: 'text'
|
||||
// highlight-start
|
||||
access: {
|
||||
create: () => true,
|
||||
read: () => true,
|
||||
update: () => true,
|
||||
delete: () => true,
|
||||
},
|
||||
// highlight-end
|
||||
};
|
||||
],
|
||||
}
|
||||
```
|
||||
7
docs/Access-Control/examples.mdx
Normal file
7
docs/Access-Control/examples.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Access Control Examples
|
||||
label: Examples
|
||||
order: 20
|
||||
---
|
||||
|
||||
Show examples of how to write access control functions.
|
||||
9
docs/Authentication/accessing-logged-in-user.mdx
Normal file
9
docs/Authentication/accessing-logged-in-user.mdx
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
title: Accessing the User
|
||||
label: Accessing the User
|
||||
order: 40
|
||||
---
|
||||
|
||||
Talk about how to access the User in custom code like hooks and access control. The User is on the req.
|
||||
|
||||
Show code examples.
|
||||
18
docs/Authentication/config.mdx
Normal file
18
docs/Authentication/config.mdx
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Authentication Config
|
||||
label: Config
|
||||
order: 10
|
||||
---
|
||||
|
||||
Talk about how to configure authentication here.
|
||||
|
||||
Need to cover:
|
||||
|
||||
1. What collection to use for Admin panel and how there can only be one
|
||||
1. Can have multiple auth collections
|
||||
1. Token expiration
|
||||
1. Email verification
|
||||
1. Security (max login, lock time)
|
||||
1. API keys
|
||||
1. Depth to populate (performance impact)
|
||||
1. Cookie settings (HTTP only discussion)
|
||||
43
docs/Authentication/operations.mdx
Normal file
43
docs/Authentication/operations.mdx
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Authentication Operations
|
||||
label: Operations
|
||||
order: 30
|
||||
---
|
||||
|
||||
Talk about Auth operations here.
|
||||
|
||||
#### Me
|
||||
|
||||
Returns null or logged in user with token (useful for HTTP only)
|
||||
|
||||
#### Create operation modifications
|
||||
|
||||
Discuss if verification is required, etc etc
|
||||
|
||||
#### Init
|
||||
|
||||
Checks if there have been users created, checks Admin access
|
||||
|
||||
#### Login
|
||||
|
||||
HTTP-only cookies, token response. Discuss max login attempts
|
||||
|
||||
#### Logout
|
||||
|
||||
Removes HTTP-only cookie
|
||||
|
||||
#### Refresh
|
||||
|
||||
Refreshes token (requires valid token)
|
||||
|
||||
#### Register First User
|
||||
|
||||
Allows for anyone to register first user through UI
|
||||
|
||||
#### Forgot Password
|
||||
|
||||
Takes an email, sends email to that address. Discuss how to customize email
|
||||
|
||||
#### Access
|
||||
|
||||
Shows what the user can and cant do.
|
||||
7
docs/Authentication/security.mdx
Normal file
7
docs/Authentication/security.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Authentication Security
|
||||
label: Security
|
||||
order: 20
|
||||
---
|
||||
|
||||
Talk about how Payload securely authenticates here.
|
||||
7
docs/Authentication/using-middleware.mdx
Normal file
7
docs/Authentication/using-middleware.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Using the Payload Auth Middleware
|
||||
label: Using the Middleware
|
||||
order: 50
|
||||
---
|
||||
|
||||
Talk about how to use `payload.authenticate()` outside of Payload - show examples
|
||||
7
docs/Components/overview.mdx
Normal file
7
docs/Components/overview.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Custom Components
|
||||
label: Overview
|
||||
order: 10
|
||||
---
|
||||
|
||||
Talk about how to build custom components. Show a list of all components that can be swapped out.
|
||||
7
docs/Configuration/blocks.mdx
Normal file
7
docs/Configuration/blocks.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Block Configs
|
||||
label: Blocks
|
||||
order: 40
|
||||
---
|
||||
|
||||
Talk about how to write block configs here.
|
||||
20
docs/Configuration/collections.mdx
Normal file
20
docs/Configuration/collections.mdx
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: Collection Configuration
|
||||
label: Collections
|
||||
order: 20
|
||||
---
|
||||
|
||||
Talk about how to write collection configs here.
|
||||
|
||||
TODO: What collections are and what they represent
|
||||
|
||||
### Stand-alone file
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
slug: 'customer',
|
||||
labels: {
|
||||
singular: 'Customer',
|
||||
plural: 'Customers',
|
||||
}
|
||||
}
|
||||
7
docs/Configuration/globals.mdx
Normal file
7
docs/Configuration/globals.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Global Configs
|
||||
label: Globals
|
||||
order: 30
|
||||
---
|
||||
|
||||
Talk about how to write Globals configs here.
|
||||
7
docs/Configuration/main.mdx
Normal file
7
docs/Configuration/main.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: The Main Config
|
||||
label: Main
|
||||
order: 10
|
||||
---
|
||||
|
||||
Talk about how to write the main config here.
|
||||
298
docs/Fields/overview.mdx
Normal file
298
docs/Fields/overview.mdx
Normal file
@@ -0,0 +1,298 @@
|
||||
---
|
||||
title: Fields Overview
|
||||
label: Overview
|
||||
order: 10
|
||||
---
|
||||
|
||||
<Banner type="info">
|
||||
Fields are the building blocks of Payload. Collections and Globals both use Fields to define the shape of the data that they store. Payload offers a wide-array of field-types - both simple and complex.
|
||||
</Banner>
|
||||
|
||||
## Field types
|
||||
|
||||
The `type` property on a field determines how the input will be rendered in the admin interface, what values it can accept, and how it is presented in the API.
|
||||
|
||||
```js
|
||||
// Collection config
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
name: 'my-field',
|
||||
type: 'text', // highlight-line
|
||||
label: 'Text',
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Simple Types
|
||||
|
||||
#### `text`
|
||||
|
||||
Plain text
|
||||
|
||||
#### `textarea`
|
||||
|
||||
Large blocks of text. No formatting.
|
||||
|
||||
#### `number`
|
||||
|
||||
Simple number input
|
||||
|
||||
#### `checkbox`
|
||||
|
||||
Boolean value that renders a checkbox
|
||||
|
||||
#### `date`
|
||||
|
||||
Renders date-picker
|
||||
|
||||
#### `email`
|
||||
|
||||
Email. Includes validation.
|
||||
|
||||
#### `code`
|
||||
|
||||
Monospaced code block
|
||||
|
||||
#### `richText`
|
||||
|
||||
Large formatted text. Includes rich text editor in the admin interface.
|
||||
|
||||
#### `select`
|
||||
|
||||
Renders a select box with any number of options
|
||||
|
||||
Options:
|
||||
|
||||
- `hasMany` - Allows for multiple options to be selected
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'select',
|
||||
label: 'Select',
|
||||
type: 'select',
|
||||
hasMany: true // Optional
|
||||
options: [
|
||||
{
|
||||
value: 'option-1',
|
||||
label: 'Option 1 Label',
|
||||
}, {
|
||||
value: 'option-2',
|
||||
label: 'Option 2 Label',
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
#### `radio`
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'radioGroup',
|
||||
label: 'Radio Group Example',
|
||||
type: 'radio',
|
||||
options: [
|
||||
{
|
||||
value: 'option-1',
|
||||
label: 'Options 1 Label',
|
||||
},
|
||||
{
|
||||
value: 'option-2',
|
||||
label: 'Option 2 Label',
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
### Complex Types
|
||||
|
||||
More powerful types but require more complex configuration
|
||||
|
||||
#### `upload`
|
||||
|
||||
Allows file and image upload. Useful for uploaded assets that can be referenced and re-used.
|
||||
|
||||
_TODO: Link to Upload configuration docs_
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'image',
|
||||
type: 'upload',
|
||||
label: 'Image',
|
||||
relationTo: 'media', // A collection with the `upload` properties configured
|
||||
}
|
||||
```
|
||||
|
||||
#### `row`
|
||||
|
||||
Rows allow for deeper nesting of values. They have their own set of fields.
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
label: 'Text',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'number',
|
||||
label: 'Number',
|
||||
type: 'number',
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
#### `array`
|
||||
|
||||
An array of the specified fields
|
||||
|
||||
Options:
|
||||
|
||||
- `minRows` - Minimum number of items required
|
||||
- `maxRows` - Maximum number of items allowed
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'array',
|
||||
label: 'Array',
|
||||
type: 'array',
|
||||
minRows: 2, // Optional
|
||||
maxRows: 4, // Optional
|
||||
fields: [
|
||||
{
|
||||
name: 'textField',
|
||||
label: 'Text Field',
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'checkbox',
|
||||
label: 'Checkbox',
|
||||
type: 'checkbox'
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### `group`
|
||||
|
||||
A way to group related fields together. They will be rendered as a group in the admin interface.
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'group',
|
||||
label: 'Group',
|
||||
name: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
name: 'nestedText1',
|
||||
label: 'Nested Text 1',
|
||||
type: 'text',
|
||||
}, {
|
||||
name: 'nestedText2',
|
||||
label: 'Nested Text 2',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
```
|
||||
|
||||
#### `blocks`
|
||||
|
||||
Repeat any type of content any number of times
|
||||
|
||||
The `blocks` property takes an array of the allowed fields
|
||||
|
||||
_TODO: Link to more powerful and complex examples_
|
||||
|
||||
Options:
|
||||
|
||||
- `minRows` - Minimum number of items required
|
||||
- `maxRows` - Maximum number of items allowed
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'page',
|
||||
type: 'blocks',
|
||||
label: 'Page',
|
||||
labels: {
|
||||
singular: 'Page',
|
||||
plural: 'Pages',
|
||||
},
|
||||
minRows: 2, // Optional
|
||||
maxRows: 4, // Optional
|
||||
blocks: [
|
||||
{
|
||||
slug: 'quote'
|
||||
label: 'Quote',
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
slug: 'testimonial',
|
||||
label: 'Testimonial',
|
||||
type: 'textarea'
|
||||
},
|
||||
{
|
||||
slug: 'cta',
|
||||
label: 'Call To Action',
|
||||
type: 'text'
|
||||
}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## Common Options
|
||||
|
||||
Most fields have the ability to use the following options
|
||||
|
||||
#### `defaultValue`
|
||||
|
||||
Initial value for the field
|
||||
|
||||
#### `required`
|
||||
|
||||
`true/false` value if the field is required to be populated
|
||||
|
||||
#### `localized`
|
||||
|
||||
`true/false` value to enable localization on the field
|
||||
|
||||
#### `admin`
|
||||
|
||||
The `admin` is an optional object with properties that specify how the field should be represented in the admin interface.
|
||||
|
||||
Properties:
|
||||
|
||||
- `position` - If specified as `sidebar`, the field will show in the admin interface's sidebar
|
||||
- `width` - A percentage value ie. `50%` that will control the max-width of the field
|
||||
- `readOnly` - `true/false` to set the field to read-only after it is saved
|
||||
|
||||
### Common Options Example
|
||||
|
||||
```js
|
||||
// Collection config
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
name: 'my-field',
|
||||
type: 'text',
|
||||
label: 'Text'
|
||||
// highlight-start
|
||||
admin: {
|
||||
position: 'sidebar',
|
||||
width: '50%',
|
||||
readOnly: true,
|
||||
}
|
||||
// highlight-end
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
11
docs/GraphQL/config.mdx
Normal file
11
docs/GraphQL/config.mdx
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: GraphQL Overview
|
||||
label: Overview
|
||||
order: 10
|
||||
---
|
||||
|
||||
Go over GraphQL configuration options.
|
||||
|
||||
- Naming conventions
|
||||
- List of all queries and mutations w/ examples
|
||||
- Context
|
||||
7
docs/GraphQL/extending.mdx
Normal file
7
docs/GraphQL/extending.mdx
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Adding your own Queries and Mutations
|
||||
label: Custom Queries and Mutations
|
||||
order: 20
|
||||
---
|
||||
|
||||
Talk about how to add your own queries and mutations.
|
||||
253
docs/Guides/blog-api.mdx
Normal file
253
docs/Guides/blog-api.mdx
Normal file
@@ -0,0 +1,253 @@
|
||||
---
|
||||
title: Blog API From Scratch
|
||||
label: Blog API
|
||||
order: 20
|
||||
---
|
||||
|
||||
In this guide, we will be creating a Blog API from scratch.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- Node
|
||||
- npm or yarn
|
||||
- MongoDB server
|
||||
|
||||
## Initial Setup
|
||||
|
||||
Let's get started by creating a project in a blank directory
|
||||
|
||||
```sh
|
||||
yarn init -y
|
||||
```
|
||||
|
||||
We then will install Payload and Express
|
||||
|
||||
```sh
|
||||
yarn add payload express
|
||||
```
|
||||
|
||||
### Server
|
||||
|
||||
Create a file named `server.js` in the root folder with the following contents
|
||||
|
||||
```js
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
app.listen(3000, async () => {
|
||||
console.log('Express is now listening for incoming connections on port 3000.');
|
||||
});
|
||||
```
|
||||
|
||||
This is a basic Express application. Now let's pull in Payload and fill in the `init` parameters. `secret` and `mongoURL` can be changed as needed.
|
||||
|
||||
```js
|
||||
const express = require('express');
|
||||
const payload = require('payload'); // highlight-line
|
||||
|
||||
const app = express();
|
||||
|
||||
// highlight-start
|
||||
payload.init({
|
||||
secret: 'SECRET_KEY',
|
||||
mongoURL: 'mongodb://localhost/payload-blog',
|
||||
express: app,
|
||||
})
|
||||
// highlight-end
|
||||
|
||||
app.listen(3000, async () => {
|
||||
console.log('Express is now listening for incoming connections on port 3000.');
|
||||
});
|
||||
```
|
||||
|
||||
### Payload Configuration
|
||||
|
||||
Next, let's get some basics put into our `payload.config.js` file
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
serverURL: 'http://localhost:3000',
|
||||
collections: [],
|
||||
}
|
||||
```
|
||||
|
||||
#### Collections
|
||||
|
||||
We'll need a few different collections for our blog:
|
||||
|
||||
- Posts
|
||||
- Categories
|
||||
- Tags
|
||||
|
||||
The Posts will have the ability to have a single category and multiple tags
|
||||
|
||||
Let's create a `collections` directory and create a `.js` file for each
|
||||
|
||||
```js:title=Posts.js
|
||||
module.exports = {
|
||||
slug: 'posts',
|
||||
labels: {
|
||||
singular: 'Post',
|
||||
plural: 'Posts',
|
||||
},
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
label: 'Title',
|
||||
type: 'text'
|
||||
},
|
||||
{
|
||||
name: 'content',
|
||||
label: 'Content',
|
||||
type: 'textarea',
|
||||
},
|
||||
{
|
||||
name: 'category',
|
||||
label: 'Category',
|
||||
type: 'relationship',
|
||||
relationTo: 'categories', // Categories Slug // highlight-line
|
||||
},
|
||||
{
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
type: 'relationship',
|
||||
relationTo: 'tags', // Tags Slug // highlight-line
|
||||
hasMany: true, // Allow multiple tags per post
|
||||
},
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
```js:title=Categories.js
|
||||
module.exports = {
|
||||
slug: 'categories',
|
||||
labels: {
|
||||
singular: 'Category',
|
||||
plural: 'Categories',
|
||||
},
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
```js:title=Tags.js
|
||||
module.exports = {
|
||||
slug: 'tags',
|
||||
labels: {
|
||||
singular: 'Tag',
|
||||
plural: 'Tags',
|
||||
},
|
||||
admin: {
|
||||
useAsTitle: 'name',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
Once these are created, we can pull them into the `collections` array in our `payload.config.js`
|
||||
|
||||
```js:title=payload.config.js
|
||||
const Admins = require('./collections/Admins');
|
||||
// highlight-start
|
||||
const Posts = require('./collections/Posts');
|
||||
const Categories = require('./collections/Categories');
|
||||
const Tags = require('./collections/Tags');
|
||||
// highlight-end
|
||||
|
||||
module.exports = {
|
||||
serverURL: 'http://localhost:3000',
|
||||
admin: {
|
||||
user: 'admins',
|
||||
},
|
||||
collections: [
|
||||
Admins,
|
||||
// highlight-start
|
||||
Posts,
|
||||
Categories,
|
||||
Tags
|
||||
// highlight-end
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### Create Content
|
||||
|
||||
**TODO: Should a guide like this use the Admin interface or `curl`?**
|
||||
|
||||
Navigate to the admin interface at `http://localhost:3000/admin` and create your first user.
|
||||
|
||||
Then create some Categories, Tags, and a Post.
|
||||
|
||||
Let's use `curl` to quickly create some data. The following commands will create 2 tags and 1 category.
|
||||
|
||||
```sh
|
||||
curl -H "Content-Type: application/json" -X POST -d '{"name": "JavaScript"}' http://localhost:3000/api/tags
|
||||
curl -H "Content-Type: application/json" -X POST -d '{"name": "TypeScript"}' http://localhost:3000/api/tags
|
||||
curl -H "Content-Type: application/json" -X POST -d '{"name": "Code"}' http://localhost:3000/api/categories
|
||||
```
|
||||
|
||||
We'll then make a request to create a Post, this will inclue a relationship to the category and tags created previously.
|
||||
|
||||
TODO: Somehow retrieve tag and category IDs then include them in a request to create a Post
|
||||
|
||||
Once complete, navigate to `http://localhost:3000/api/posts`, and you should see something similar to the following:
|
||||
|
||||
```js
|
||||
{
|
||||
"docs": [
|
||||
{
|
||||
"tags": [
|
||||
{
|
||||
"name": "TypeScript",
|
||||
"createdAt": "2020-11-13T11:48:05.993Z",
|
||||
"updatedAt": "2020-11-13T11:48:05.993Z",
|
||||
"id": "5fae72758315da656fb3a8f0"
|
||||
},
|
||||
{
|
||||
"name": "JavaScript",
|
||||
"createdAt": "2020-11-13T11:48:00.064Z",
|
||||
"updatedAt": "2020-11-13T11:48:00.064Z",
|
||||
"id": "5fae72708315da656fb3a8ef"
|
||||
}
|
||||
],
|
||||
"title": "My Title",
|
||||
"content": "This is some content",
|
||||
"category": {
|
||||
"name": "Code",
|
||||
"createdAt": "2020-11-13T11:48:10.351Z",
|
||||
"updatedAt": "2020-11-13T11:48:36.358Z",
|
||||
"id": "5fae727a8315da656fb3a8f1"
|
||||
},
|
||||
"createdAt": "2020-11-13T11:50:14.312Z",
|
||||
"updatedAt": "2020-11-13T11:50:14.312Z",
|
||||
"id": "5fae72f68e314b67609e05d1"
|
||||
}
|
||||
],
|
||||
"totalDocs": 1,
|
||||
"limit": 10,
|
||||
"totalPages": 1,
|
||||
"page": 1,
|
||||
"pagingCounter": 1,
|
||||
"hasPrevPage": false,
|
||||
"hasNextPage": false,
|
||||
"prevPage": null,
|
||||
"nextPage": null
|
||||
}
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user