Compare commits

...

686 Commits

Author SHA1 Message Date
James
5b22d91579 0.0.141 2020-11-20 08:45:47 -05:00
James
09b9ce60ad Merge branch 'master' of github.com:keen-studio/payload 2020-11-20 08:45:34 -05:00
James
e20a07e06f 0.0.140 2020-11-20 08:45:10 -05:00
James
0204aa962c moves types into separate folder 2020-11-20 08:45:06 -05:00
Jarrod Flesch
d46051435f Merge branch 'master' of github.com:trouble/payload 2020-11-19 16:52:40 -05:00
Jarrod Flesch
0d56cf4496 properly passes overrideAccess through populationPromise when finding by ID 2020-11-19 16:52:33 -05:00
James
61dae53fc3 Merge branch 'master' of github.com:keen-studio/payload 2020-11-19 10:27:18 -05:00
James
f5377120c4 yarn 2020-11-19 10:27:15 -05:00
James
780106c7f6 declares type for sanitizeConfig 2020-11-19 10:27:09 -05:00
James
811e4bb265 avoids eslint on typescript files 2020-11-19 10:26:56 -05:00
James
111cab1564 runs editorconfig on ts files 2020-11-19 10:26:08 -05:00
Elliot DeNolf
131dd51c39 feat: use react-toastify for notifications 2020-11-19 10:00:48 -05:00
James
0d333ce7da exports Forbidden 2020-11-18 16:02:31 -05:00
James
fa7ad6e9ed adds locale back to admin 2020-11-17 21:25:33 -05:00
James
9b6dd0c771 Merge branch 'master' of github.com:keen-studio/payload 2020-11-17 21:00:27 -05:00
James
a7a0624235 removes requirement of field-level hooks to returrn value 2020-11-17 21:00:00 -05:00
James
8f08269916 better identifies field-level access control 2020-11-17 20:59:35 -05:00
Elliot DeNolf
dbd305acc5 feat: show email creds when explicitly set to 'mock' 2020-11-17 17:33:05 -05:00
Elliot DeNolf
83d32e4449 feat: validate admin user 2020-11-17 16:59:36 -05:00
James
78d7aa7707 0.0.139 2020-11-17 16:45:57 -05:00
Jacob Fletcher
a3ecd7324a - removes duplicative user lookup in login operation
- enables depth and access control in login operation
2020-11-17 16:41:15 -05:00
Jarrod Flesch
87525001f7 adds payload to the express router globally 2020-11-17 15:50:05 -05:00
Elliot DeNolf
f52836a7e3 fix: missed a file 2020-11-17 15:01:50 -05:00
Elliot DeNolf
fe536f0628 refactor: pull all base fields out of collection sanitize 2020-11-17 14:39:10 -05:00
James
1de5ac8cba 0.0.138 2020-11-17 11:27:33 -05:00
Elliot DeNolf
2624ad5f7e fix: properly concat verification and locking fields 2020-11-17 11:24:33 -05:00
Dan Ribbens
7fb23ab6be Merge pull request #451 from trouble/feature/timestamps-default-true
timestamps default to true for collections
2020-11-17 08:53:14 -05:00
Dan Ribbens
208e6fe47a timestamps default to true for collections 2020-11-17 08:51:05 -05:00
Elliot DeNolf
9a1c1f64c0 feat: add blind index for encrypting API Keys 2020-11-16 14:59:47 -05:00
Elliot DeNolf
65fe6c2f95 fix unnecessary reducing of locales 2020-11-15 20:19:41 -05:00
Elliot DeNolf
65ade57c94 /me return null if wrong user collection 2020-11-15 19:34:25 -05:00
Elliot DeNolf
2565005cc0 feat: add license key to access routej 2020-11-15 19:20:20 -05:00
Elliot DeNolf
de4538bf5f docs(hooks): add beforeOperation hook 2020-11-15 15:01:01 -05:00
James
2b80020393 Merge branch 'master' of github.com:keen-studio/payload 2020-11-14 16:40:51 -05:00
James
1166e85fad removes potentially unused code in hookPromise 2020-11-13 22:07:58 -05:00
James
e5193476c4 reorders removeInternalFields 2020-11-13 22:07:08 -05:00
James
5dbf276e82 adds beforeOperation hook, cleans operations 2020-11-13 13:54:10 -05:00
Elliot DeNolf
a6f3230915 docs(guides): blog API draft 2020-11-13 07:32:34 -05:00
Elliot DeNolf
0694a09abd fix: auth json schema didn't allow auth as boolean 2020-11-13 05:59:17 -05:00
Elliot DeNolf
dceeeaac6a fix: allow e-mail to be unconfigured, remove default fromName and fromAddress 2020-11-13 05:30:28 -05:00
James
bdc92bcdf0 Merge branch 'master' of github.com:keen-studio/payload 2020-11-12 16:43:47 -05:00
Elliot DeNolf
06a6056e1c docs(rest-api): first draft 2020-11-12 12:39:08 -05:00
James
4b951279a8 0.0.137 2020-11-12 11:36:31 -05:00
Jacob Fletcher
3984f8b36c exposes express json options in config 2020-11-12 11:35:34 -05:00
Elliot DeNolf
b9b3a0dcc7 docs(fields): add line highlighting, move common options to bottom 2020-11-11 20:32:01 -05:00
Elliot DeNolf
7caa025278 docs(fields): add common options 2020-11-11 15:39:21 -05:00
Elliot DeNolf
27e5dc4d55 docs(hooks): move Lifecycle section down 2020-11-11 15:38:50 -05:00
Elliot DeNolf
63fc9b76be docs(fields): first pass 2020-11-11 13:42:39 -05:00
James
5c1e2846a2 0.0.136 2020-11-10 16:30:04 -05:00
Jarrod Flesch
73c45944f4 adds res cookie options from collection config to logout route 2020-11-10 16:29:27 -05:00
Dan Ribbens
86171c500f Merge pull request #444 from trouble/rename-auth-verify-email
auth email verify anyOf type to allow one or both subject and html
2020-11-10 11:16:36 -05:00
Dan Ribbens
1010334f76 improve auth veryify description 2020-11-10 11:14:18 -05:00
Dan Ribbens
f44869f7cb auth email verify anyOf type to allow one or both subject and html properties 2020-11-10 11:12:08 -05:00
James
4b0c5cc9a2 Merge branch 'master' of github.com:keen-studio/payload 2020-11-10 09:18:35 -05:00
James
36b8f46f7e 0.0.135 2020-11-10 09:18:16 -05:00
James
d5ecbc96a3 fixes bug with not using formatted vals in buildQuery 2020-11-10 09:17:33 -05:00
Elliot DeNolf
760114b718 Merge pull request #443 from trouble/docs-hooks 2020-11-10 00:38:48 -05:00
Elliot DeNolf
76068637fb docs(hooks): add examples 2020-11-10 00:36:48 -05:00
Elliot DeNolf
bed0b1c04e docs(hooks): add lifecycle and more collection hooks 2020-11-10 00:29:21 -05:00
Elliot DeNolf
8a1cdc3f7d fix(hooks): incorrect hook executing for field-level afterChange 2020-11-09 22:27:50 -05:00
Elliot DeNolf
462f7f1f42 docs(hooks): first pass 2020-11-09 16:28:38 -05:00
James
10a657e9d7 0.0.134 2020-11-09 14:53:18 -05:00
James
ae7a94bf47 Merge branch 'master' of github.com:keen-studio/payload 2020-11-09 14:47:35 -05:00
James
e12bdb320d fixes bug with removing internal fields 2020-11-09 14:47:26 -05:00
Dan Ribbens
f667937aef Merge pull request #442 from trouble/rename-auth-verify-email
rename collection auth email verification to verify and add to collec…
2020-11-09 14:26:35 -05:00
Dan Ribbens
20c508cb12 remove default auth property for collection schema 2020-11-09 14:21:58 -05:00
Dan Ribbens
c00e5e8904 rename collection auth email verification to verify and add to collection schema json 2020-11-09 14:10:37 -05:00
Dan Ribbens
c6b00c9aca Merge pull request #430 from trouble/schema-json
Schema json
2020-11-09 08:26:12 -05:00
James
7154a1e35c 0.0.133 2020-11-08 14:52:38 -05:00
James
734662a9b4 includes docs in npm export 2020-11-08 14:52:29 -05:00
James
b11aa62001 ensures token is delivered properly within verification email 2020-11-08 14:48:56 -05:00
James
f4c066e475 allows async email html generation 2020-11-08 14:48:43 -05:00
James
1d7a789604 0.0.132 2020-11-08 10:32:24 -05:00
James
3f74eff0fe adds additional docs 2020-11-08 10:31:59 -05:00
James
2a2d33cd0b fixes bug with delete operation and hasWhereAccess 2020-11-08 10:31:53 -05:00
James
4e61ae84f7 adds installation doc 2020-11-08 08:32:00 -05:00
James
165634d127 scaffolds more docs 2020-11-07 15:51:05 -05:00
James
082c6d010c Merge branch 'master' of github.com:keen-studio/payload 2020-11-07 13:27:46 -05:00
James
62f65d5ffb updates docs 2020-11-07 13:27:43 -05:00
Elliot DeNolf
738698edad add key to collection list 2020-11-05 11:48:56 -05:00
James
a83064ed97 lints buildQuery 2020-11-04 09:08:27 -05:00
James
5ef407ba17 0.0.131 2020-11-04 09:07:26 -05:00
James
21fabfcb29 Merge branch 'master' of github.com:keen-studio/payload 2020-11-04 09:07:12 -05:00
James
521f250688 re-yarn 2020-11-04 09:07:09 -05:00
James
df33ceca79 sanitizes null strings provided to relationship queries 2020-11-04 09:07:02 -05:00
James
0ffbd2ee0f removes leftover autopopulate in schema construction 2020-11-04 09:05:54 -05:00
Dan Ribbens
4d64569c34 merge master 2020-11-02 16:01:32 -05:00
Dan Ribbens
32c025a2fa enforce boolean timestamps on collection schema 2020-11-02 15:53:47 -05:00
Dan Ribbens
58fa48a4da validates some parts of payload config schema and collections 2020-11-02 15:31:33 -05:00
Elliot DeNolf
699aa1b60f remove console.log 2020-11-02 13:44:02 -05:00
Elliot DeNolf
a00c565a62 allow unlock from admin UI 2020-11-02 13:42:06 -05:00
James
90bac7f4ab 0.0.130 2020-10-28 16:20:48 -04:00
James
ec2cda20cf exposes exp in login 2020-10-28 16:20:41 -04:00
James
1702261a15 0.0.129 2020-10-28 16:15:58 -04:00
James
bd85d621f5 Merge branch 'master' of github.com:keen-studio/payload 2020-10-28 16:15:51 -04:00
Jacob Fletcher
61bc485bf1 extracts exp from user 2020-10-28 16:15:32 -04:00
James
eaf89794ab 0.0.128 2020-10-28 10:33:59 -04:00
Jacob Fletcher
6a6b23d3d6 Merge branch 'master' of github.com:trouble/payload 2020-10-28 10:33:30 -04:00
Jacob Fletcher
5bb8a6d6d5 migrates away from optional chaining in express/responses/formatError 2020-10-28 10:33:21 -04:00
James
cc73db9bf0 0.0.127 2020-10-28 10:30:19 -04:00
James
48d2e230a3 Merge branch 'master' of github.com:keen-studio/payload 2020-10-28 10:29:40 -04:00
James
0ac24bc4f2 removes optional chaining 2020-10-28 10:29:37 -04:00
James
29e148763a adds custom component to docs 2020-10-27 09:46:19 -04:00
Elliot DeNolf
354d1527e1 fix: only allow /logout on current user's collection 2020-10-26 20:41:59 -04:00
Elliot DeNolf
ffa56e6c81 fix: /me only works on current user's collection 2020-10-26 20:41:49 -04:00
James
edcc6b56c8 Merge branch 'master' of github.com:keen-studio/payload 2020-10-26 16:56:31 -04:00
James
7e2f3e21ba updates docs for testing purposes 2020-10-26 16:56:26 -04:00
James
0d238085ba exports banner 2020-10-26 16:56:12 -04:00
James
082bf2fba4 adds ability to override depth on auth user 2020-10-26 16:56:03 -04:00
Elliot DeNolf
56a3ccaee8 rename useAuthentication to useAuth 2020-10-26 16:34:46 -04:00
Dan Ribbens
3f4c66467d add trustProxy to payload config and set express trust proxy on payload init (#429) 2020-10-26 16:17:49 -04:00
Dan Ribbens
85ccd80906 fix package import 2020-10-26 06:20:54 -04:00
Dan Ribbens
de539d00b6 schema validation using ajv with collections and assign default values 2020-10-26 06:01:33 -04:00
Dan Ribbens
f37c9eec04 WIP: add schema validation for payload config 2020-10-25 17:03:35 -04:00
James
9fd3e8d84f Merge branch 'master' of github.com:keen-studio/payload 2020-10-24 12:15:49 -04:00
James
07c917e33d adds webpack cli 2020-10-24 12:15:44 -04:00
Dan Ribbens
10c51f11c5 Merge branch 'rest-gql-errors' into schema-json 2020-10-23 13:14:35 -04:00
Dan Ribbens
5431b8ebcc Merge pull request #428 from trouble/rest-gql-errors
Rest gql errors
2020-10-23 13:12:40 -04:00
Dan Ribbens
e233551d0b cleanup graphql init 2020-10-23 13:11:16 -04:00
Dan Ribbens
5d4d1bf60c add trustProxy to payload config and set express trust proxy on payload init 2020-10-23 13:06:07 -04:00
Dan Ribbens
e6bfe00843 add cross-env to build scripts 2020-10-23 11:11:39 -04:00
Dan Ribbens
5c3b20643a Merge pull request #426 from trouble/rest-gql-errors
validation error respone and handling change
2020-10-22 17:07:22 -04:00
Dan Ribbens
e9600802a8 handle validation error data object to display field level error messages 2020-10-22 16:44:25 -04:00
Dan Ribbens
0aa2e5138c rest errorHandler now returns the same object as graphql for validation errors 2020-10-22 16:39:36 -04:00
James
27dad40d5c 0.0.126 2020-10-21 18:02:42 -04:00
James
646b46528d removes breaking optional chaining in graphql error handler 2020-10-21 18:02:36 -04:00
James
e097e924f2 0.0.125 2020-10-21 17:59:02 -04:00
James
777aaf9afd Merge branch 'master' of github.com:keen-studio/payload 2020-10-21 17:58:49 -04:00
James
221ec0bb10 takes copy of all docs found by ID in case they were memoized 2020-10-21 17:58:36 -04:00
Dan Ribbens
67ff273a9e use logger in graphql error handler 2020-10-20 09:45:57 -04:00
Dan Ribbens
397d36291d Merge pull request #425 from trouble/graphql-errors
gql errors include formatted field validation data
2020-10-20 09:36:27 -04:00
Dan Ribbens
a4066e4802 gql errors include formatted field validation data 2020-10-20 01:14:19 -04:00
Elliot DeNolf
88e24ba452 add ability to disable graphql playground in production 2020-10-19 20:18:24 -04:00
Elliot DeNolf
c7b377b84c fix: use proper user object in me operation 2020-10-18 01:34:36 -04:00
James
05a06a9aa8 allows for auth to be specified as true with no options 2020-10-17 15:08:39 -04:00
Elliot DeNolf
90a686ea0b Merge pull request #422 from trouble/query-exists 2020-10-16 21:45:41 -04:00
Elliot DeNolf
215df7ff9e handle graphql exists type 2020-10-16 21:42:55 -04:00
Elliot DeNolf
0758f01120 wip: exists query 2020-10-16 17:13:52 -04:00
James
bb7a910377 0.0.124 2020-10-16 16:05:32 -04:00
James
078293833d exposes local verifyEmail operation 2020-10-16 14:17:12 -04:00
James
99f61150d6 Merge branch 'master' of github.com:keen-studio/payload 2020-10-16 11:26:02 -04:00
James
ac64013a07 improves error messages in verifyEmail operation 2020-10-16 10:10:13 -04:00
James
5735b4bbec adds specificity to verified users 2020-10-16 08:48:33 -04:00
James
f0374d5772 adds an option to show hidden fields within local operations 2020-10-15 18:12:19 -04:00
James
20a9dcf6fe ensures hidden fields do not get added to graphql schemas 2020-10-15 16:48:02 -04:00
James
d0ef42a16b improves email api 2020-10-15 16:47:35 -04:00
James
18077d98bf allows for generating custom emails via collection config 2020-10-15 16:47:04 -04:00
James
cda4792ff7 simplifies verification view 2020-10-15 16:44:59 -04:00
Elliot DeNolf
76df2bc75a adjust FileGraphic to fill thumbnail area 2020-10-15 15:00:16 -04:00
Elliot DeNolf
e52b639e64 fix: upload sort from SelectExisting 2020-10-15 14:07:53 -04:00
Elliot DeNolf
75604e9b6c add 'date' to sortable field types 2020-10-15 11:21:54 -04:00
Elliot DeNolf
e058933192 test: add automatic account unlock test 2020-10-14 22:15:25 -04:00
Elliot DeNolf
a12ae0a1b6 test: add account lock test 2020-10-14 22:15:19 -04:00
Elliot DeNolf
5e0fd00b4e Merge pull request #420 from trouble/verify-tests 2020-10-14 16:45:15 -04:00
Elliot DeNolf
b4a43475ac test: add user verification test 2020-10-14 16:42:22 -04:00
Elliot DeNolf
f0bc59dd0c test: remove faker 2020-10-14 15:08:47 -04:00
Elliot DeNolf
c5aba71aa7 fix: show field requirement of 1 when Array/Blocks are required but no minRows specified 2020-10-14 11:49:26 -04:00
Elliot DeNolf
cac6a8869b test: split out collection tests into multiple files 2020-10-14 10:39:00 -04:00
Elliot DeNolf
787691859d remove verificationToken after verified 2020-10-13 16:48:06 -04:00
Elliot DeNolf
bf0d20461a fix: handle undefined in DateCell and DatePicker, homogenize formatting 2020-10-13 13:27:55 -04:00
Elliot DeNolf
7da73626ac fix: less_than_equal filter 2020-10-13 12:22:38 -04:00
James
8086120703 Merge branch 'master' of github.com:keen-studio/payload 2020-10-12 18:24:23 -04:00
James
7afa815467 0.0.123 2020-10-12 18:24:03 -04:00
James
5400500360 implements custom date and email gql scalars 2020-10-12 18:23:55 -04:00
Elliot DeNolf
ccae4014ec Merge pull request #416 from trouble/upload-tests 2020-10-12 16:59:32 -04:00
Elliot DeNolf
02279a769d test: upload with same name 2020-10-12 16:56:49 -04:00
Elliot DeNolf
c766a5a40e test: update upload 2020-10-12 16:31:05 -04:00
Elliot DeNolf
7ac2d0dcff test: remove beforeRead hook, messes with tests 2020-10-12 16:22:40 -04:00
James
6dfa1616ea 0.0.122 2020-10-12 16:14:13 -04:00
James
8a0411d6b1 condenses exports 2020-10-12 16:14:05 -04:00
Elliot DeNolf
fc63a692be test: add update upload 2020-10-12 15:21:36 -04:00
James
2b9b504573 0.0.121 2020-10-12 15:13:46 -04:00
James
fd9453889e sanitizes json before it comes out of global and collection find operations 2020-10-12 15:13:37 -04:00
James
dea21a0aae 0.0.120 2020-10-12 13:30:58 -04:00
James
12c520c3b1 re-adds node-sass as dependency 2020-10-12 13:30:51 -04:00
James
abc0383ecc 0.0.119 2020-10-12 13:24:32 -04:00
James
bb4dce09df allows for disableErrors to be passed through local findByID 2020-10-12 13:24:28 -04:00
James
6b932168ce 0.0.118 2020-10-12 12:41:48 -04:00
James
681bba82a9 removes mongoose-hidden, updates globals accordingly 2020-10-12 12:41:31 -04:00
Elliot DeNolf
4cfde3eba7 fix: do not attempt to delete upload if file doesn't exist 2020-10-12 11:04:57 -04:00
Elliot DeNolf
71633b1c8d test: check for actual files on create 2020-10-12 10:56:16 -04:00
Elliot DeNolf
2eb863aff0 test: extract out headers 2020-10-12 10:40:50 -04:00
Elliot DeNolf
5aede8affb fix component compilation 2020-10-11 14:29:46 -04:00
Elliot DeNolf
09dfb9793a fix webpack paths for both unix and windows 2020-10-11 14:14:21 -04:00
Elliot DeNolf
09897de77d add sort complex 2020-10-11 14:10:42 -04:00
Dan Ribbens
0362290d40 fix windows compatibility with webpack 2020-10-11 12:04:26 -04:00
James
57ef9fe623 fixes broken tests 2020-10-10 18:37:31 -04:00
James
38f08d54e3 0.0.117 2020-10-10 18:28:27 -04:00
James
84191ec8fd renames client to admin, sets up component library 2020-10-10 18:28:17 -04:00
James
e88be6b251 0.0.116 2020-10-09 13:39:14 -04:00
James
3bec424d05 Merge branch 'master' of github.com:keen-studio/payload 2020-10-09 13:39:07 -04:00
James
fc56a42fb0 fixes issue with relationship field and null value 2020-10-09 13:39:02 -04:00
James
05a5cc16bd further removes dependency on mongoose-hidden 2020-10-09 13:38:51 -04:00
Elliot DeNolf
c99b2f35f4 add disableScrollOnSuccess per-collection 2020-10-09 12:24:17 -04:00
Elliot DeNolf
8ae7457a3f add missing autoComplete attribute on password fields 2020-10-09 12:06:29 -04:00
Elliot DeNolf
bb8a04dd7b add style and width props for Group, Array, and Blocks 2020-10-09 11:45:58 -04:00
James
a681f5f725 builds unlock operation 2020-10-09 11:04:36 -04:00
Elliot DeNolf
613552de0a add style and width props for Blocks 2020-10-09 10:07:16 -04:00
Elliot DeNolf
cd38d37242 enforce maxRows on Arrays and Blocks 2020-10-09 10:07:10 -04:00
James
6b6b503ef0 0.0.115 2020-10-09 08:04:13 -04:00
James
f880072697 fixes bug with adding blocks and arrays due to async buildStateFromSchema 2020-10-08 23:03:37 -04:00
James
ffc3f10177 adds indication for readOnly Array and Blocks when no rows are present 2020-10-08 21:41:47 -04:00
James
f9b7e3239e adds both singular and plural labels to Blocks and Array, adjusts impacted files accordingly 2020-10-08 21:33:37 -04:00
James
09cc61c96a fixes modal scroll 2020-10-08 20:09:00 -04:00
James
a6325c69f4 Merge branch 'master' of github.com:keen-studio/payload 2020-10-08 19:32:36 -04:00
James
2f1b1a02b1 enables default values in new rows of array / block fields 2020-10-08 19:32:10 -04:00
James
727c5a4a53 styles baseline richText 2020-10-08 19:31:42 -04:00
James
918d3bd2bc fixes bug with clearing hasMany relationship field values 2020-10-08 19:31:26 -04:00
Elliot DeNolf
2d7bacad09 don't render 'Add Blocks' button when readOnly 2020-10-08 17:00:41 -04:00
James
234ed07ad6 Merge branch 'master' of github.com:keen-studio/payload 2020-10-08 16:18:08 -04:00
Elliot DeNolf
964fdf779a make rich text respect readOnly 2020-10-08 16:05:23 -04:00
Elliot DeNolf
40afb5e8fa add default value test for normal fields 2020-10-08 10:16:05 -04:00
James
72c0145816 0.0.114 2020-10-08 09:15:24 -04:00
James
12eb33b5c9 fixes bug with fromAddress in sanitizeConfig 2020-10-08 09:14:50 -04:00
Elliot DeNolf
ddb238c7e4 add blocks cell tests 2020-10-08 07:09:24 -04:00
Elliot DeNolf
32980fcafc Merge pull request #410 from trouble/tests-reorg 2020-10-08 06:29:30 -04:00
Elliot DeNolf
db6315a621 fix date cell test for timezone in CI 2020-10-08 06:27:19 -04:00
Elliot DeNolf
6bf0c2aab6 ci: add client tests 2020-10-08 05:53:47 -04:00
Elliot DeNolf
3dc9ddcb52 add some cell type tests 2020-10-08 05:50:07 -04:00
Elliot DeNolf
352dfa9a09 finish configuring client tests 2020-10-08 05:20:52 -04:00
Elliot DeNolf
60a3e680dd move tests dir to root 2020-10-08 05:01:48 -04:00
Elliot DeNolf
18f98e24e5 disable logging during tests, remove unused test:unit script, and add 'test' task to run all 2020-10-08 04:55:06 -04:00
Elliot DeNolf
c599522e44 isolate api tests inside tests/api 2020-10-08 04:50:33 -04:00
Elliot DeNolf
64fef7d380 implement basic react testing suite 2020-10-07 17:20:10 -04:00
James
6381d4cf6b 0.0.113 2020-10-07 16:52:58 -04:00
James
91016ec206 removes image-size in favor of probe-image-size to handle CMYK jpgs 2020-10-07 16:52:48 -04:00
James
9aeab9548d ensures default values work for Group and Array 2020-10-07 16:43:08 -04:00
James
69d7f21b56 partially working buildStateFromSchema 2020-10-07 16:26:56 -04:00
James
9de596605b fixes bug with localization 2020-10-07 16:18:01 -04:00
James
650edcf56a reduces padding on position-panel 2020-10-07 16:17:49 -04:00
James
2c4dedff2c only loads uploads if modal is open 2020-10-07 15:55:25 -04:00
James
870e39961c implements env-based bundle analyzer 2020-10-07 15:55:16 -04:00
James
319148ca68 adds default value collection 2020-10-07 15:54:53 -04:00
James
6dac68606b adds build scripts 2020-10-07 15:54:42 -04:00
James
9716d008a9 Merge branch 'master' of github.com:keen-studio/payload 2020-10-07 15:39:08 -04:00
James
b5fd68c3dc 0.0.112 2020-10-07 15:10:48 -04:00
James
eea9d14749 ensures modals have proper Z index, allows Upload field to handle deleted files gracefully 2020-10-07 15:10:39 -04:00
Elliot DeNolf
77de6e4b60 fix: initial form state 2020-10-07 14:53:55 -04:00
James
58f68e3bda 0.0.111 2020-10-07 14:51:50 -04:00
James
1ea3763185 better handles failed form submissions, allows customization of file uploads 2020-10-07 14:51:42 -04:00
James
920251f296 0.0.110 2020-10-07 12:42:41 -04:00
James
dffb554ebe fixes bug in Number field type 2020-10-07 12:42:32 -04:00
James
7255f6108f 0.0.109 2020-10-06 14:40:57 -04:00
James
078392f2c5 0.0.107 2020-10-06 14:40:52 -04:00
James
c2e9407f50 removes unused arg in findByID memoization 2020-10-06 14:39:53 -04:00
James
a5a4f1490e Merge branch 'master' of github.com:keen-studio/payload 2020-10-06 14:39:10 -04:00
James Mikrut
e20555f9cf Memoize populate (#408)
* Revert "0.0.108"

This reverts commit 7aafe49662.

* Revert "swaps out fast-memoize for micro-memoize that supports async"

This reverts commit 33d8ec8a13.

* Revert "implements a named populate function to memoize"

This reverts commit fb73e772af.

* Revert "0.0.107"

This reverts commit c2692e9b4a.

* reverts back to 106

* memoizes findByID
2020-10-06 14:38:20 -04:00
James
791a222d28 reverts back to 106 2020-10-06 13:16:36 -04:00
James
cb97090d88 Revert "0.0.107"
This reverts commit c2692e9b4a.
2020-10-06 13:15:33 -04:00
James
923cdc7b6a Revert "implements a named populate function to memoize"
This reverts commit fb73e772af.
2020-10-06 13:15:09 -04:00
James
19369b4c33 Revert "swaps out fast-memoize for micro-memoize that supports async"
This reverts commit 33d8ec8a13.
2020-10-06 13:15:00 -04:00
James
4ec230e8a0 Revert "0.0.108"
This reverts commit 7aafe49662.
2020-10-06 13:14:52 -04:00
James
7aafe49662 0.0.108 2020-10-06 09:47:13 -04:00
James
33d8ec8a13 swaps out fast-memoize for micro-memoize that supports async 2020-10-06 09:47:05 -04:00
James
fb73e772af implements a named populate function to memoize 2020-10-06 09:11:09 -04:00
James
c2692e9b4a 0.0.107 2020-10-06 08:58:30 -04:00
James
a0d6fe5ca7 memoizes the Populate function 2020-10-06 08:58:25 -04:00
James
7f65e68e82 0.0.106 2020-10-05 22:14:44 -04:00
James
d9f78fc5bf removes unused salt and hash hidden options 2020-10-05 22:14:11 -04:00
James
b2a5279bcb hides fields manually, removes isLocked virtual in favor of a defined Payload field 2020-10-05 22:12:33 -04:00
James
28baba822b 0.0.105 2020-10-05 21:43:13 -04:00
James
3b4875b754 fixes bug with incoming richText stringified JSON 2020-10-05 21:42:47 -04:00
James
8ce88deda2 fixes bug with create / update improperly reducing locales 2020-10-05 21:37:31 -04:00
James
4527658027 misc responsive fixes 2020-10-05 21:18:29 -04:00
James
8057c0ecb8 abstracts performFieldOperations into functions for performance reasons 2020-10-05 20:26:04 -04:00
James
eb74a42386 0.0.104 2020-10-05 17:09:12 -04:00
James
d589a90a42 allows for local payload initialization 2020-10-05 17:08:59 -04:00
James
bf3d05cb40 fixes bug with registerFirstUser 2020-10-05 17:08:44 -04:00
James
7bd4859a31 0.0.103 2020-10-05 10:40:22 -04:00
James
9af097c39c restores required initialState via form context 2020-10-05 10:40:14 -04:00
James
7f47cdacbb enables lean mongoose queries for all find operations 2020-10-05 10:25:35 -04:00
James
d85cbde7a7 0.0.102 2020-10-04 20:42:50 -04:00
James
79284941db fixes a grave mistake 2020-10-04 20:42:36 -04:00
James
35c11aa7aa 0.0.101 2020-10-04 15:31:15 -04:00
James
5ac2b1fb3d adds richText Relationship WIP 2020-10-04 15:30:47 -04:00
James
0a5e8ab618 implements maxDepth 2020-10-04 15:30:38 -04:00
James
5ae267f743 updates styles of RichText, improves its API 2020-10-04 12:50:14 -04:00
James
bc48e92aea fixes bug with autocompleted input fields 2020-10-04 12:41:03 -04:00
James
98af494dd6 further styles RichText and its Link element 2020-10-03 15:55:59 -04:00
James
31487fb022 adds a method to deserialize pasted HTML into RichText 2020-10-03 15:55:38 -04:00
James
e00a2eeef7 fixes fields with less than 100% width on mobile 2020-10-03 15:55:21 -04:00
James
c5ea2dcd2a revises the way that negative field type gutter works 2020-10-03 15:55:07 -04:00
James
e9c2b46c97 extends Popup to be more usable 2020-10-03 15:54:19 -04:00
James
043d3fffbf fixes bug with window info breakpoints 2020-10-03 15:54:00 -04:00
James
febe213e80 implements accessibility measures and finishes Link richText element 2020-10-03 13:04:15 -04:00
James
0764f34c64 adds accessibility to buttons 2020-10-03 11:38:33 -04:00
James
3dbf9ac27c properly sets user to null when logged out 2020-10-03 11:20:35 -04:00
James
eccb4383a1 fixes DeleteDocument and leaveWithoutSaving incompatibility 2020-10-03 11:07:06 -04:00
James
31180bfc2b 0.0.99 2020-10-02 21:36:15 -04:00
James
c6105d9ed3 ensures NODE_ENV is set properly within client 2020-10-02 21:36:02 -04:00
James
3b82d1ccba runs admin static through compression middleware 2020-10-02 21:28:40 -04:00
James
9fe8a09ac9 0.0.98 2020-10-02 21:11:20 -04:00
James
18a59f84ab migrates all custom components to new pattern 2020-10-02 21:11:08 -04:00
James
c28f78cb8a further optimizes webpack bundle 2020-10-02 20:46:08 -04:00
James
18baefed0d progress to code-splitting 2020-10-02 18:47:43 -04:00
James
f56eeddff4 0.0.97 2020-10-02 15:46:46 -04:00
James
f5561b4b4f adds safety checks for building initial form state with no blockType 2020-10-02 15:46:27 -04:00
James
d42171d465 Merge branch 'master' of github.com:keen-studio/payload 2020-10-02 15:02:41 -04:00
Elliot DeNolf
f3d56fe435 add code cell type 2020-10-02 12:37:00 -04:00
Elliot DeNolf
52e9e4daa7 fix default checkbox cell value 2020-10-02 12:34:28 -04:00
Elliot DeNolf
dde76572e3 disappearing cancel button was bothering me 2020-10-02 12:06:59 -04:00
Elliot DeNolf
df4563274b disable scroll on save for upload media modal 2020-10-02 11:04:02 -04:00
Elliot DeNolf
6e93bd006e fix checkbox style 2020-10-02 10:27:33 -04:00
Elliot DeNolf
814cc9658c add checkbox cell type for boolean values 2020-10-02 10:21:23 -04:00
Elliot DeNolf
efc6d0adf1 fix graphQL tests 2020-10-02 09:45:58 -04:00
James
f37fe42c70 0.0.96 2020-10-01 14:58:07 -04:00
James
3359cd4e9b ensures reset password sends back a new user 2020-10-01 14:57:59 -04:00
Elliot DeNolf
2b80c5fda6 remove unused email props 2020-10-01 13:20:07 -04:00
Elliot DeNolf
4c2bcb2933 fix no data in useAsTitle field 2020-10-01 13:20:01 -04:00
James
96c1362a5d flattens me auth type to match collection type 2020-10-01 11:37:20 -04:00
James
5f3b1aec0a increases max rateLimit 2020-10-01 11:37:04 -04:00
James
942afd96fe returns user with login 2020-10-01 11:36:58 -04:00
James
39ddde082c 0.0.95 2020-10-01 09:17:45 -04:00
James
9b384e8192 removes dependency of passing publicENV through options on init 2020-10-01 09:17:37 -04:00
James
09543831b9 fixes webpack prod env config 2020-10-01 09:02:15 -04:00
James
eb0b5870a3 Merge branch 'master' of github.com:keen-studio/payload 2020-10-01 08:51:55 -04:00
James
49c03135a9 0.0.94 2020-10-01 08:51:37 -04:00
James
22ba992b6d removes dotenv-webpack for a more declarative approach 2020-10-01 08:51:25 -04:00
Elliot DeNolf
553d3ebd48 disable pointer events if code field is readOnly 2020-09-30 22:25:30 -04:00
James
f80bda89b6 0.0.93 2020-09-30 12:13:25 -04:00
James
722f2fc88d merges master 2020-09-30 12:13:19 -04:00
James
c89d2e0f01 Merge branch 'master' of github.com:keen-studio/payload 2020-09-30 12:13:10 -04:00
James
7aab4214b7 implements a way to skip over certain ips in rate limiter 2020-09-30 12:12:59 -04:00
Elliot DeNolf
6294333c88 highlight token field on generation 2020-09-30 11:03:55 -04:00
James
98afd9c53b 0.0.92 2020-09-30 10:34:20 -04:00
James
6ccca08319 tries to export appropriate files once more 2020-09-30 10:34:15 -04:00
James
f497fdde22 0.0.91 2020-09-30 10:31:54 -04:00
James
d73fdf6572 includes more files in npm export 2020-09-30 10:31:50 -04:00
James
0e6f790734 Merge branch 'master' of github.com:keen-studio/payload 2020-09-30 08:54:25 -04:00
James
18774c05ea 0.0.90 2020-09-30 08:53:38 -04:00
James
b3dda3c070 standardizes custom component naming to proper nouns 2020-09-30 08:53:15 -04:00
James
d9e62e9a6d fixes bug with graphql maxComplexity default value 2020-09-30 07:49:29 -04:00
Elliot DeNolf
3f5518aa3a Merge pull request #401 from trouble/token-gen-confirm
add token generation confirmation modal
2020-09-29 22:31:16 -04:00
Elliot DeNolf
0c12b8dfda add token generation confirmation modal 2020-09-29 22:29:30 -04:00
James
a53ac62164 0.0.89 2020-09-28 18:26:06 -04:00
James
8fa63c7131 fixes paths for custom icon and logo 2020-09-28 18:25:54 -04:00
James
5599b8bd30 0.0.88 2020-09-28 18:15:30 -04:00
James
5694258b74 cleans performFieldOperations 2020-09-28 18:15:26 -04:00
James
a974c908b5 fixes bug in Upload cell, returns nullAsUndefineds to object-to-formdata 2020-09-28 18:15:08 -04:00
James
6d7d996d61 properly runs exported field-types and hooks through babel 2020-09-28 16:25:42 -04:00
James
da4d9c5e71 0.0.87 2020-09-28 16:02:53 -04:00
James
c409ac985c removes console logs 2020-09-28 16:02:41 -04:00
James
62072e2d0f 0.0.86 2020-09-28 15:49:36 -04:00
James
18e08ad5a7 revises RichText structure and functionality 2020-09-28 15:49:20 -04:00
Elliot DeNolf
ae8cc7b9ed fix: upload cell prop validation errors 2020-09-28 15:35:01 -04:00
Elliot DeNolf
06fd32786d fix: add back image field 2020-09-28 15:18:43 -04:00
Elliot DeNolf
2f5c13aac3 fix: select cell component handle strings and arrays of strings 2020-09-28 15:16:54 -04:00
Elliot DeNolf
5025972450 add select cell component 2020-09-28 13:37:18 -04:00
Elliot DeNolf
e7d3f77560 Merge pull request #400 from trouble/tune-package
add files whitelist to package.json
2020-09-28 12:50:04 -04:00
Elliot DeNolf
f171adc88d add files whitelist to package.json 2020-09-28 12:48:10 -04:00
Elliot DeNolf
e24428c42c Merge pull request #399 from trouble/cell-components 2020-09-28 10:30:40 -04:00
Elliot DeNolf
e849f0f49e add upload cell component 2020-09-28 10:27:02 -04:00
Elliot DeNolf
b011163d90 use singular label from block items 2020-09-28 00:46:54 -04:00
Elliot DeNolf
0492603ac7 add custom cell types for array, textarea, and richtext 2020-09-28 00:05:10 -04:00
James
15a488c03f creates a better pattern for how to render table cells 2020-09-27 15:33:49 -04:00
James
77096cb252 Merge branch 'master' of github.com:keen-studio/payload 2020-09-27 15:07:46 -04:00
James
6efeafe819 fixes modals scrolling to top of screen 2020-09-27 15:07:32 -04:00
Elliot DeNolf
dabc5749d4 Merge pull request #398 from trouble/graphql-query-complexity 2020-09-27 15:03:55 -04:00
Elliot DeNolf
79fc3f72a6 implement graphql query complexity limits 2020-09-27 15:01:35 -04:00
Elliot DeNolf
7c2de28de9 Merge pull request #397 from trouble/lock-adjustments
some adjustments to how locking and verification work
2020-09-26 23:48:07 -04:00
Elliot DeNolf
83f77d3a05 some adjustments to how locking and verification work 2020-09-26 23:46:09 -04:00
James
5b71a3cb60 0.0.85 2020-09-26 17:52:35 -04:00
James
04650a86a5 handles either relative or absolute paths for upload directories 2020-09-26 17:50:12 -04:00
James
69b4f9f59f 0.0.84 2020-09-25 16:27:40 -04:00
James
4df979565e re-adds baseFields 2020-09-25 16:24:26 -04:00
James
193cdbbe5e Merge branch 'master' of github.com:keen-studio/payload 2020-09-25 16:21:11 -04:00
Elliot DeNolf
a634a5c00c Merge pull request #396 from trouble/rate-limiter 2020-09-25 14:29:43 -04:00
Elliot DeNolf
c19ccd5df4 implement account locking on too many attempts and unlocking after time window 2020-09-25 14:22:13 -04:00
Elliot DeNolf
57c6afa3a9 implement basic rate limiting for /api routes 2020-09-24 23:25:59 -04:00
Elliot DeNolf
9354d86af2 feat(ts): add collection hook types
Signed-off-by: Elliot DeNolf <denolfe@gmail.com>
2020-09-24 17:20:21 -04:00
Elliot DeNolf
791de301cc Merge pull request #395 from trouble/verify-graphql 2020-09-24 17:08:07 -04:00
Elliot DeNolf
87ccdae795 implement verify graphql resolver 2020-09-24 16:39:38 -04:00
Elliot DeNolf
a412e68e89 update typescript types 2020-09-24 11:19:41 -04:00
Elliot DeNolf
98e2f2be08 fix: NotFound bad call to useConfig 2020-09-24 11:08:13 -04:00
Elliot DeNolf
b8b5ca17ed Merge pull request #390 from trouble/verify-view 2020-09-24 10:56:42 -04:00
Elliot DeNolf
96ccebdedd add 'already activated' response 2020-09-24 10:54:42 -04:00
James
59da900a1d 0.0.83 2020-09-24 09:36:27 -04:00
James
fbc4429648 fixes bug with combining AND clauses, extends graphql id operations 2020-09-24 09:36:21 -04:00
James
3feec809e6 0.0.82 2020-09-23 20:15:45 -04:00
James
8dd3298f9a performance improvements 2020-09-23 20:14:27 -04:00
Elliot DeNolf
0c3986917f implement verify view 2020-09-23 16:04:19 -04:00
James
4c11134141 0.0.81 2020-09-23 12:31:08 -04:00
James
45c824c042 allows entire client folder to be parsed by babel/register 2020-09-23 12:31:02 -04:00
James
181d27e33d 0.0.80 2020-09-23 12:20:52 -04:00
James
0e225e1ab1 properly runs babel/register against @payloadcms/payload as a node module 2020-09-23 12:20:44 -04:00
Jarrod Flesch
5676f22ede adds h2-h6 to the rich text editor and style tweaks 2020-09-23 11:22:17 -04:00
James
e9cc178ed7 fixes bug with PurpleBackground demo 2020-09-23 10:04:37 -04:00
James
09a3c859c1 finishes RichText PoC 2020-09-23 10:02:48 -04:00
James
628d68ed2d ensures tests work with new babel config 2020-09-21 21:58:16 -04:00
James
fe99952561 implements babel transpilation of config, removes customComponents logic 2020-09-21 17:31:19 -04:00
James
9c28086ba4 preloads all custom elements and leaves within RichText 2020-09-20 19:01:34 -04:00
James
f8c225316b WIP richText refactor 2020-09-20 18:29:12 -04:00
James
df1f381354 Merge branch 'master' of github.com:keen-studio/payload 2020-09-19 19:32:04 -04:00
James
939a2923d3 implements an easier pattern of pointing to files within config 2020-09-19 19:31:04 -04:00
Elliot DeNolf
0e15f8376c underscore prefix verification fields 2020-09-19 15:03:47 -04:00
Elliot DeNolf
c9d9d5269d make verified hidden 2020-09-19 14:53:06 -04:00
Elliot DeNolf
97f8f2b749 Merge pull request #389 from trouble/verify-jwt-and-apikey
check verification for jwt and apikey
2020-09-19 14:51:38 -04:00
Elliot DeNolf
ea21480230 check verification for jwt and apikey 2020-09-19 14:49:19 -04:00
Elliot DeNolf
2918bbeeca Merge pull request #388 from trouble/verified-login
only allow verified accounts to login
2020-09-19 14:32:08 -04:00
Elliot DeNolf
ac1aea23dc only allow verified accounts to login 2020-09-19 14:29:19 -04:00
Elliot DeNolf
d478bd0e34 Merge pull request #387 from trouble/email-verification 2020-09-19 13:41:25 -04:00
Elliot DeNolf
1695e4e685 implement verification of email against db 2020-09-19 13:39:51 -04:00
James
20bf4680db 0.0.79 2020-09-19 12:15:53 -04:00
James
4f3dd59d25 removes server-config babel plugin in favor of manually blacklisting server modules 2020-09-19 12:15:24 -04:00
James
dde3a35b16 converts radio graphql types to enum 2020-09-19 08:33:03 -04:00
James
a964860e55 0.0.78 2020-09-17 09:19:12 -04:00
James
41dcdabe9c Merge branch 'master' of github.com:keen-studio/payload 2020-09-17 09:19:02 -04:00
James
8ad96452a0 additional field sanitization 2020-09-17 09:18:53 -04:00
Elliot DeNolf
9f426913a2 export all interfaces 2020-09-16 22:06:12 -04:00
Elliot DeNolf
e8376a5662 Merge pull request #386 from trouble/typescript-support 2020-09-16 21:53:17 -04:00
Elliot DeNolf
08dcd7f8b2 better typing for payload function responses 2020-09-16 21:51:34 -04:00
Elliot DeNolf
03e1b730b5 type remaining fields in payload config 2020-09-16 21:08:14 -04:00
James
8252c409d4 0.0.77 2020-09-16 17:22:02 -04:00
James
70ae5b1a19 fixes bug with Relationship field needlessly fetchinig options 2020-09-16 17:21:53 -04:00
James
0d42060882 0.0.76 2020-09-16 13:56:20 -04:00
James
e35b212781 builds relationship whereInput graphQL type 2020-09-16 13:56:02 -04:00
Elliot DeNolf
08731594cb implement payload types module 2020-09-16 12:04:42 -04:00
Elliot DeNolf
c439297223 wip: implement sendVerificationEmail 2020-09-16 10:47:21 -04:00
James
88d80aec55 0.0.75 2020-09-16 09:05:10 -04:00
James
6f6289a069 allows for proper extension of graphql queries / mutations 2020-09-16 09:04:50 -04:00
Elliot DeNolf
af65787862 implement basic typescript support 2020-09-16 00:25:12 -04:00
Elliot DeNolf
a39cec2b76 use crypto for verification token 2020-09-15 14:26:55 -04:00
Elliot DeNolf
f20feae4d9 conditionally add email verification fields to schema 2020-09-15 14:20:28 -04:00
James
2d1169ac66 removes leftover reference to auth update 2020-09-15 11:40:43 -04:00
James
966dd7a40f allows for user override in local operations 2020-09-15 08:57:49 -04:00
James
eee835696c adds control over overrideAccess in findByID 2020-09-14 21:53:11 -04:00
James
e95edbd3e4 fixes css imports like an adult 2020-09-14 21:25:11 -04:00
James
b462fe5f77 stringifies globals before sending, fixes async bug 2020-09-14 21:21:13 -04:00
James
a1865ed5fb Merge branch 'master' of github.com:keen-studio/payload 2020-09-14 21:04:44 -04:00
James
209d812239 fixes bug with relationship population in graphql resolver 2020-09-14 21:04:17 -04:00
James
4e3cc2bc05 comments out breaking graphql errors 2020-09-14 21:04:02 -04:00
James
f5731f2fc8 moves position of beforeRead operation 2020-09-14 21:03:50 -04:00
James
29b608d6f8 properly imports css in DatePicker 2020-09-14 21:03:06 -04:00
James
a10dd738c0 removes old lines in gitignore 2020-09-14 21:02:52 -04:00
James
0fb96ff3e9 fixes bug with loading css in DatePicker 2020-09-14 21:02:40 -04:00
Elliot DeNolf
55488c5c2e Merge pull request #384 from trouble/global-update-access
fix global update's execution of access
2020-09-14 20:50:43 -04:00
Elliot DeNolf
5345eb993a fix global update's execution of access 2020-09-14 17:34:56 -04:00
Elliot DeNolf
8f67ee4ac3 Merge pull request #382 from trouble/local-crud-globals 2020-09-14 17:03:21 -04:00
James
9f8b1d9521 fixes bug with ensuring hasMany relationships have initial values 2020-09-13 12:24:04 -04:00
James
d4c4418a3e 0.0.74 2020-09-13 12:06:14 -04:00
James
bb5f747052 flattens create / register, update / authUpdate 2020-09-13 12:06:02 -04:00
Elliot DeNolf
f2f8ffbbb2 implement global update 2020-09-13 08:40:28 -04:00
James
fab4c0ed76 fixes accidentally running hooks for non-populated subdocs, waits for hooks before running population 2020-09-12 22:56:15 -04:00
James
7b3cefd4ef fixes bug with zero-based radio values 2020-09-12 22:55:18 -04:00
James
ad483da837 changes timestamps to opt-out 2020-09-12 22:55:05 -04:00
James
01d49ccd36 removes console log 2020-09-12 17:48:46 -04:00
James
7ceadc15a3 just wasted about a half hour of time on this 2020-09-12 17:45:55 -04:00
James
3caf81d9f7 redirects to NotFound properly when editing a document that does not exist 2020-09-12 16:42:04 -04:00
James
dd6740e109 only shows LeaveWithoutSaving if user is logged in 2020-09-12 16:36:23 -04:00
James
28e4cf6726 fixes bug in code field 2020-09-12 16:33:14 -04:00
James
95e38a568f adds Code field 2020-09-12 16:24:03 -04:00
James
43f1f41179 0.0.73 2020-09-11 15:12:17 -04:00
James
698a9ead04 fixes bug with field sanitization and JWT graphql type 2020-09-11 15:12:02 -04:00
James
bd3f628d55 Merge branch 'master' of github.com:keen-studio/payload 2020-09-11 14:11:51 -04:00
James
14d702ff8d improves graphql name formatting 2020-09-11 14:11:33 -04:00
James
dd5acae76f only sets nullable gql type if no admin condition 2020-09-11 14:11:23 -04:00
James
9de51bbf02 fixes gql in relationships with many relations 2020-09-11 14:11:10 -04:00
James
9c44a159b9 formats radio values as strings within validation 2020-09-11 12:50:41 -04:00
James
43e3162c7d fixes bug within FileDetails when no sizes present 2020-09-11 12:49:44 -04:00
Elliot DeNolf
2b81e887ad implement global find 2020-09-11 11:33:26 -04:00
Elliot DeNolf
bfd492b7ed Merge pull request #377 from trouble/validate-relationships 2020-09-10 21:49:46 -04:00
Elliot DeNolf
bf452c23bc Add tests for sanitizeFields 2020-09-10 21:47:55 -04:00
Elliot DeNolf
da3495cb4b fix MissingFieldType missing export 2020-09-10 21:18:01 -04:00
Elliot DeNolf
899a158843 fix parameter ordering for sanitizeFields calls 2020-09-10 21:17:46 -04:00
Elliot DeNolf
163daf5816 validate global relationships 2020-09-10 19:35:55 -04:00
Elliot DeNolf
7fbab16b22 validate relationships within blocks, gettin' recursive with it 2020-09-10 19:17:57 -04:00
Elliot DeNolf
17b8335c3c validate relationTo on fields 2020-09-10 18:07:07 -04:00
Elliot DeNolf
93930d1125 Merge pull request #376 from trouble/mongoose-indexing
Disable auto-indexing, index if set to true or if unique
2020-09-10 16:41:54 -04:00
Elliot DeNolf
9cb630f98d Disable auto-indexing, index if set to true or if unique 2020-09-10 13:02:09 -04:00
Jarrod Flesch
f695bd8c1d increases font size on date picker times 2020-09-09 14:25:12 -04:00
Jarrod Flesch
8a8222995f better date validation, date-picker style updates 2020-09-08 15:11:18 -04:00
Jarrod Flesch
ca24263c17 removes duplicate key from babel-loader removeObjectProperties 2020-09-08 13:31:25 -04:00
James
0bf0dd7d5e 0.0.72 2020-09-08 10:47:25 -04:00
James
ef3a70cc38 bumps slate 2020-09-08 10:47:21 -04:00
James
6fe09c8264 fixes bugs within auth / graphQL 2020-09-07 14:47:03 -04:00
James
4616e7fa16 sends fields on mount within useFieldType 2020-09-05 17:44:41 -04:00
James
d99788f6f7 0.0.71 2020-09-05 12:25:29 -04:00
James
8a1bd762ba implements a way to add custom express middleware 2020-09-05 12:23:39 -04:00
James
c760863f8c enables Upload GraphQL field resolver 2020-09-05 12:19:32 -04:00
James
ed5c3b55f1 0.0.70 2020-09-01 18:22:04 -04:00
James
7d0e2820cc implements cookie expiration, streamlines cookie options on collection config level 2020-09-01 18:21:51 -04:00
James
f381b9261a 0.0.69 2020-08-29 16:24:35 -04:00
James
01f170ba73 further revises initialState fixes to Array, Blocks 2020-08-29 16:24:27 -04:00
James
a53e24904f fixes state initialization in Array and Blocks 2020-08-29 12:08:26 -04:00
James
423cdbd63f removes field from state if failing condition 2020-08-29 12:08:12 -04:00
James
e38c0e687f fixes bug in Radio field type 2020-08-29 12:07:32 -04:00
James
9e82f9d02e fixes bugs with GraphQL when no locale is present 2020-08-29 12:07:06 -04:00
James
5f9c48494a fixes bug in refresh resolver 2020-08-29 12:06:12 -04:00
James
155db092c4 adds safety check to getExtractJWT 2020-08-29 12:05:40 -04:00
James
87522ff7d6 0.0.68 2020-08-28 15:07:22 -04:00
James
e6b435e88e fixes bug with forgotPassword 2020-08-28 15:07:16 -04:00
James
8c78a0a773 0.0.67 2020-08-28 13:43:29 -04:00
James
597f7d3075 fixes bugs with columns in List, logs errors within email config, creates local delete operation 2020-08-28 13:43:17 -04:00
James
9da8aca015 Merge branch 'master' of github.com:keen-studio/payload 2020-08-28 11:29:34 -04:00
Elliot DeNolf
13aa1eb13d Merge pull request #367 from trouble/better-error-logging
Handle values other than string in APIError
2020-08-26 23:35:38 -04:00
Elliot DeNolf
918228c9dc Handle values other than string in APIError 2020-08-26 23:14:28 -04:00
James
92a25867ff 0.0.66 2020-08-26 18:34:59 -04:00
James
f698594137 implements lowercasing in forgotPassword 2020-08-26 18:34:39 -04:00
James
c15dff4afb Merge branch 'master' of github.com:keen-studio/payload 2020-08-26 18:31:31 -04:00
James
985db67d48 ensures login is done with lowercase 2020-08-26 18:31:25 -04:00
Elliot DeNolf
30c5eeaff9 Merge pull request #364 from trouble/favicon
Implement favicon and og image
2020-08-25 21:39:06 -04:00
Elliot DeNolf
fd81085b54 Implement favicon and og image 2020-08-25 21:37:17 -04:00
James
9955621f0a 0.0.65 2020-08-25 16:06:27 -04:00
James
599a693f5b fixes bugs with columns in List view 2020-08-25 16:06:21 -04:00
James
da6a9a2ba7 0.0.64 2020-08-25 14:39:33 -04:00
James
7002752744 adds serverURL to CSRF 2020-08-25 14:39:27 -04:00
James
53ed79ecbc code splits heavy field types 2020-08-25 12:21:37 -04:00
James
1e342f8bee further improvements to splitting browser and server code 2020-08-25 11:05:19 -04:00
James
d19576978b implements the removal of server-side code from client bundle 2020-08-25 10:36:34 -04:00
James
af59822510 implements pattern for removing properties from config 2020-08-25 09:44:53 -04:00
James
f45f93ce38 0.0.63 2020-08-24 20:35:35 -04:00
James
0d1ffdcb4b removes webpack bundle analyzer 2020-08-24 20:35:25 -04:00
James
b197d780c1 passes id of document to access operations where required 2020-08-24 17:02:03 -04:00
James
45da1369ca 0.0.62 2020-08-24 12:55:16 -04:00
James
478d1cf5ee removes webpack-node-externals 2020-08-24 12:55:02 -04:00
James
ec0b2c6a5b 0.0.61 2020-08-24 12:19:27 -04:00
James
3a5881cc48 lowercases email on registration, adds node-webpack-externals to dev webpack cfg 2020-08-24 12:19:24 -04:00
Dan Ribbens
13c857f753 Merge pull request #360 from trouble/gql-spec-bug
fix gql random test failures
2020-08-23 18:56:57 -04:00
Dan Ribbens
5091a40e96 fix gql random test failures 2020-08-23 18:53:10 -04:00
Dan Ribbens
1cf45f7fa9 Merge pull request #359 from trouble/select-field-validation
Select field validation
2020-08-23 18:38:30 -04:00
Dan Ribbens
b49b531ce4 select field validation for hasMany fields 2020-08-23 18:35:28 -04:00
James
7553e14a8b merges master 2020-08-23 18:12:53 -04:00
James
cb984f4d54 implements webpack-node-externals 2020-08-23 18:10:47 -04:00
Dan Ribbens
9630c2c3b2 add validation and schema enum to radio field type 2020-08-23 17:15:40 -04:00
Dan Ribbens
8bfc892f7c radio field validation on options 2020-08-23 16:49:51 -04:00
Dan Ribbens
756d275edf select field validation on options 2020-08-23 16:48:01 -04:00
Dan Ribbens
bfe7a139af Merge pull request #357 from trouble/remove-hash-salt-auth-responses
set hide option for salt and hash in auth collections
2020-08-23 16:09:56 -04:00
Dan Ribbens
95352f47ea set hide option for salt and hash in auth collections 2020-08-23 16:07:06 -04:00
Elliot DeNolf
98a9eb8d23 Merge pull request #356 from trouble/custom-index 2020-08-23 07:33:34 -04:00
Elliot DeNolf
9a62c2ab5d Use payload/config alias in Meta 2020-08-23 07:28:59 -04:00
Elliot DeNolf
9c928d497c Implement custom index 2020-08-23 07:26:02 -04:00
Elliot DeNolf
6f777dd09c Merge pull request #355 from trouble/page-titles
Implement page titles based upon active view
2020-08-22 19:59:18 -04:00
Elliot DeNolf
5777868eba Implement page titles based upon active view 2020-08-22 19:53:57 -04:00
Dan Ribbens
063b3b86c8 Merge pull request #354 from trouble/cookie-same-site
add samesite config setting to auth
2020-08-22 00:14:58 -04:00
Dan Ribbens
9ef9cca948 add samesite config setting to auth 2020-08-22 00:08:46 -04:00
James
74ac23dbc6 0.0.60 2020-08-21 17:44:05 -04:00
James
b2145a0a59 fixes Add Upload modal 2020-08-21 17:42:04 -04:00
James
fe307ecfeb fixes inability to remove file from upload field 2020-08-21 17:30:32 -04:00
James
80b99653cf fixes bugs with LeaveWithoutSaving modal 2020-08-21 17:25:51 -04:00
James
75aa92952a 0.0.59 2020-08-21 16:25:36 -04:00
James
3375963449 fixes bugs within Update operation 2020-08-21 16:25:09 -04:00
James
f91c47bb37 fixes bug introduced with csrf 2020-08-21 15:44:03 -04:00
James
60552d9d86 implements potential csrf protection 2020-08-21 15:20:21 -04:00
James
857cf088f6 roughs out pattern for awaiting ensureIndex on all models 2020-08-21 15:19:50 -04:00
James
5c506a1db7 0.0.58 2020-08-20 16:30:31 -04:00
James
b81c7917a9 fixes a bug with block fields not being iterated through in perforFieldOperations, fixes checkboxes being sent as strings 2020-08-20 16:30:01 -04:00
James
5802011eea fixes errorHandler tests 2020-08-20 09:16:50 -04:00
James
c91f4d9e0d 0.0.57 2020-08-19 16:29:48 -04:00
James
b5690cf721 fixes bug with CORS headers 2020-08-19 16:29:35 -04:00
James
aaee4d16d1 0.0.56 2020-08-18 18:05:16 -04:00
James
5148a21769 fixes bug with forgotPassword custom expiration 2020-08-18 18:05:03 -04:00
James
ec461e2440 0.0.55 2020-08-18 17:24:40 -04:00
James
ada2b79054 implements html override in forgotPassword 2020-08-18 17:24:33 -04:00
James
3d652b2c9a 0.0.54 2020-08-18 14:50:21 -04:00
James
63bc00e8da fixese bug in auth update operation 2020-08-18 14:50:07 -04:00
James
8162b1fc93 0.0.53 2020-08-18 13:16:55 -04:00
James
a009387461 fixes bad syntax in login operation 2020-08-18 13:16:51 -04:00
James
8dbf10dc4a 0.0.52 2020-08-18 13:15:07 -04:00
James
954cd9437b Merge branch 'master' of github.com:keen-studio/payload 2020-08-18 13:14:57 -04:00
James
1c532d3719 0.0.51 2020-08-18 13:14:35 -04:00
James
273351103d adds fields within rows and other types to JWT if necessary 2020-08-18 13:14:28 -04:00
Jarrod Flesch
fd15b06773 fix: removes section title input bg, removes right gutter border line on parent hover 2020-08-18 09:15:11 -04:00
James
9efb5e881b removes a bug-producing effect in Checkbox that sets value on mount 2020-08-14 16:45:36 -04:00
James
e674bb6779 0.0.50 2020-08-14 15:51:10 -04:00
James
8df93b23b5 Merge branch 'master' of github.com:keen-studio/payload 2020-08-14 15:51:00 -04:00
James
afc47d92b5 fixes bug with authenticating via API Key 2020-08-14 15:50:50 -04:00
Elliot DeNolf
d47c8a240a Update README 2020-08-14 13:50:21 -04:00
James
9be27927c1 implements a method of overriding resetPasswordExpiration 2020-08-14 13:36:54 -04:00
James
e0c1400ee4 0.0.49 2020-08-14 13:20:15 -04:00
James
eb604a566d merges master 2020-08-14 13:17:57 -04:00
James
0b2add2e1a recursively adds block type discriminators 2020-08-14 13:17:34 -04:00
Elliot DeNolf
1ca046532d Merge pull request #345 from trouble/expose-logger
Expose logger for external use
2020-08-14 13:11:17 -04:00
Elliot DeNolf
c1843170d6 expose logger for external use 2020-08-14 13:08:50 -04:00
James
85bf65e40e fixes breaking GraphQLDate within resolvers due to JSON.stringify 2020-08-14 12:33:42 -04:00
James
2a2494366b 0.0.48 2020-08-14 10:05:01 -04:00
James
b53dbc1a27 adds update, adds way to disable email within forgotPassword operation 2020-08-14 10:04:48 -04:00
James
6c881e3c48 0.0.47 2020-08-13 18:29:23 -04:00
James
17b4251176 adds local forgotPassword, resetPassword, findByID 2020-08-13 18:29:12 -04:00
James
c7411fd347 modifies payload authenticate middleware API and exposes errorHandler 2020-08-13 16:02:19 -04:00
James
f32e7f8f4c 0.0.46 2020-08-13 10:36:02 -04:00
James
2667c6fa98 converts payload to singleton, adds local create 2020-08-13 10:35:25 -04:00
James
46309f33a2 properly sets default values if no value present on update or create 2020-08-13 09:18:02 -04:00
James
fb495d7b04 0.0.45 2020-08-12 16:41:04 -04:00
James
f8840ee8b7 adds login and register local operations 2020-08-12 16:40:51 -04:00
James
3c025377f5 0.0.44 2020-08-11 19:59:47 -04:00
James
a01b308c38 fixes bugs with DatePicker, further refinements to draggable section 2020-08-11 19:59:34 -04:00
James
53c56c537d aesthetic improvements to Group, Array, Blocks 2020-08-11 19:26:34 -04:00
James
a669ca7099 0.0.43 2020-08-11 16:01:12 -04:00
James
258d4cd62e swaps logout to POST instead of GET 2020-08-11 16:00:55 -04:00
James
fe2c1e69e5 0.0.42 2020-08-11 15:51:50 -04:00
James
a77dcaa6c2 implements proper reset password workflow within admin panel and sets cookie properly 2020-08-11 15:51:36 -04:00
James
dfd4f75c98 0.0.41 2020-08-11 14:02:28 -04:00
James
322b726be8 properly threads overrideAccess through register operation 2020-08-11 13:59:31 -04:00
James
2978509034 0.0.40 2020-08-11 12:07:57 -04:00
James
d9c1b41e08 properly replaces https in cookie domains 2020-08-11 12:07:45 -04:00
James
9538af2e92 0.0.39 2020-08-11 11:54:37 -04:00
James
2eb19876ee adds system vars to webpack dotenv 2020-08-11 11:54:28 -04:00
James
74fb5397ac 0.0.38 2020-08-11 10:55:14 -04:00
James
0630c006d5 overrides field level policies properly 2020-08-11 10:52:29 -04:00
James
71a5a525d1 simplifies Dashboard component 2020-08-10 17:37:23 -04:00
James
5ba0313b8f simplifies Default List, removes Create buttons if collection create permission is denied 2020-08-10 17:28:49 -04:00
James
7a775166b2 Merge branch 'master' of github.com:keen-studio/payload 2020-08-10 16:59:34 -04:00
Dan Ribbens
9edf4ae2da Merge pull request #340 from trouble/gitattributes
add .gitattributes
2020-08-06 08:54:49 -04:00
Dan Ribbens
fcef33ad1f add .gitattributes 2020-08-06 08:49:40 -04:00
Elliot DeNolf
cbf18d75a7 Merge pull request #339 from trouble/more-gql-tests 2020-08-05 22:09:56 -04:00
Elliot DeNolf
6f38e5c264 test(graphql): delete localized post 2020-08-05 21:58:46 -04:00
Elliot DeNolf
ead0568a94 test(graphql): read localized post 2020-08-05 21:51:42 -04:00
James
5b5acd7471 0.0.37 2020-07-31 12:12:58 -04:00
James
87e79817f7 fixes errors with client registration process 2020-07-31 12:12:36 -04:00
Elliot DeNolf
2b969b91b9 Merge pull request #338 from trouble/media-tests 2020-07-31 10:21:41 -04:00
Elliot DeNolf
609bf54c45 Fix media test if media dir doesn't exist yet 2020-07-31 10:14:31 -04:00
James
9a104b5d12 0.0.36 2020-07-31 08:12:07 -04:00
James
65eccb129f 0.0.35 2020-07-30 17:40:36 -04:00
Elliot DeNolf
022bf17b59 Assert file doesn't exist on media delete 2020-07-30 14:01:41 -04:00
James
ae7583401e allows for sanitization of string true / false in buildQuery 2020-07-30 13:39:54 -04:00
James
1ca904f164 Merge branch 'master' of github.com:keen-studio/payload 2020-07-30 13:32:15 -04:00
James
bc884e64dd revisions to field styles 2020-07-30 13:32:11 -04:00
Jarrod Flesch
89ceff24fc adjusts Icon rendering, add min height to edit sticky so save button can always be seen 2020-07-30 12:39:49 -04:00
Jarrod Flesch
47b2940358 style tweaks to FieldTypeGutters 2020-07-30 12:31:10 -04:00
Jarrod Flesch
facff24abc Merge pull request #334 from trouble/bugfix/nested-repeaters
bugfix(style): fixes nested fieldTypeGutters positioning
2020-07-30 11:20:18 -04:00
Jarrod Flesch
8f10f14bc4 bugfix(style): fixes nested fieldTypeGutters positioning 2020-07-30 11:19:45 -04:00
James
3c522930ee fixes cases where hooks return undefined 2020-07-30 10:04:17 -04:00
Elliot DeNolf
0da92c20ea Add jest debug current file and adjust Jest timeout 2020-07-30 09:46:52 -04:00
Elliot DeNolf
43db6a491d Add media delete test 2020-07-30 09:46:21 -04:00
James
ae77d68f72 0.0.34 2020-07-30 09:35:19 -04:00
James
0e76d3e79d updates globals to use form initial state, resets field state on initial state change 2020-07-30 09:25:34 -04:00
Elliot DeNolf
f0ae33f780 Add media create test 2020-07-30 08:31:48 -04:00
James
684e23fa2f adds a few safety checks to query building 2020-07-30 08:19:33 -04:00
James
bf2ed1747c 0.0.33 2020-07-30 07:27:06 -04:00
James
90a09e268f passes operation through to field hooks 2020-07-30 07:26:48 -04:00
James
0cc468ad6a fixes useThrottledEffect 2020-07-29 21:19:28 -04:00
James
16b9aab785 modifies create and update hooks to 'change' instead 2020-07-29 19:19:15 -04:00
James
749388e877 merges Group style updates 2020-07-29 13:48:05 -04:00
James
17dfa693ba opens up margin below grouped field types 2020-07-29 13:47:35 -04:00
Jarrod Flesch
2dcb80e681 merges with master 2020-07-29 13:19:47 -04:00
Jarrod Flesch
26ab75a356 Adds more style tweaks to groups
- add flex wrap to rows
- renames RenderFieldGutter to FieldTypeGutter
- removes some misc unused code
2020-07-29 13:14:37 -04:00
James
97c31faea1 waits for hooks to be resolved before validating 2020-07-29 09:34:00 -04:00
James
8b167e9a9e implements pattern for adding additional cell components within List view 2020-07-29 08:10:36 -04:00
James
d9bf8a5fcc 0.0.32 2020-07-28 21:16:48 -04:00
James
7b5dd0ac5f fixes bug with unset checkbox values sending as empty strings 2020-07-28 21:16:34 -04:00
James
210295e704 implements a way to clear relationship field values 2020-07-28 20:32:24 -04:00
James
ed56971de6 merges progress to Group styles 2020-07-28 19:50:48 -04:00
James
298948b203 supports wildcard cors header 2020-07-28 19:46:58 -04:00
James
f5b55ddbb4 fixes z-index within react-select options menu 2020-07-28 19:41:34 -04:00
James
99d083bb09 implements a way to disable duplication, disables readOnly if operation is create 2020-07-28 19:39:38 -04:00
James
455f2ab183 implements readOnly on more fields, fixes bugs with relationship 2020-07-28 19:32:41 -04:00
James
f4127e1820 0.0.31 2020-07-28 16:51:13 -04:00
James
8fa95b7851 allows readOnly to cascade through children 2020-07-28 16:50:54 -04:00
James
aefdabfd7e mysteriously fixes error handler by adding next argument 2020-07-28 14:12:57 -04:00
James
470a33f7f9 ensures payload is passed through local find operation 2020-07-28 14:08:27 -04:00
Jarrod Flesch
d179427d7b removes border-radius on editable title 2020-07-28 09:30:54 -04:00
Jarrod Flesch
599af3f924 adjusts line hover states 2020-07-28 09:24:22 -04:00
Jarrod Flesch
6e383d9005 resolves css conflicts with master 2020-07-28 09:05:45 -04:00
Jarrod Flesch
d74c1e3b93 resolves conflicts and adds top-offset-variable 2020-07-28 01:26:49 -04:00
Jarrod Flesch
c1814cbc3f adjusts the group styles and refactors how the block panels are composed 2020-07-28 01:13:33 -04:00
James
c0fef9bfde 0.0.30 2020-07-27 19:18:43 -04:00
James
1363bec776 improves styling to sticky headers in blocks 2020-07-27 19:08:37 -04:00
James
f3972430f6 merges error-handler-logging 2020-07-27 18:57:08 -04:00
James
998cb656a5 merges rte-crashing 2020-07-27 18:56:29 -04:00
James
1a8228c08b Merge branch 'bugfix/#275' of github.com:keen-studio/payload 2020-07-27 18:55:26 -04:00
James
07f9a06571 Merge branch 'bugfix/#309' of github.com:keen-studio/payload 2020-07-27 18:55:07 -04:00
James
9c8145238c adds pattern for local CRUD 2020-07-27 17:04:54 -04:00
Jarrod Flesch
3445f5bdce sticks the section header to the top of block sections - #309 2020-07-27 16:43:45 -04:00
Jarrod Flesch
8d3573d734 adds scrollbar width and adjusts popup width accordingly - #275 2020-07-27 16:08:53 -04:00
Jarrod Flesch
1fc32fa0bb removes styled-components from package.json and yarn.lock 2020-07-27 15:01:59 -04:00
Jarrod Flesch
255f6e6215 migrate slate-plugins to newest version, dropping peer dep of styled-components 2020-07-27 14:30:15 -04:00
Jarrod Flesch
1aa649782b merges with master 2020-07-27 12:38:26 -04:00
James
16d2f400c4 0.0.29 2020-07-27 12:31:42 -04:00
James
4d99594021 temporarily re-adds styled components as dependency 2020-07-27 12:31:28 -04:00
James
790c85df5a 0.0.28 2020-07-27 12:01:14 -04:00
James
0a98778ec4 Merge branch 'master' of github.com:keen-studio/payload 2020-07-27 12:01:07 -04:00
James
cc4794e5ac implements initial form state 2020-07-27 11:53:00 -04:00
Dan Ribbens
e301efdb7b add payload logger to error handler middleware 2020-07-24 10:32:41 -04:00
Elliot DeNolf
a4cf98c460 Merge pull request #321 from trouble/logger 2020-07-24 09:39:57 -04:00
Elliot DeNolf
c9e37bcef5 Better formatting for logger output 2020-07-24 09:37:49 -04:00
Elliot DeNolf
deaf5cde5f Initial logger implementation with pino 2020-07-23 21:57:11 -04:00
James
d38b8e746c removes unused dependencies 2020-07-23 19:18:24 -04:00
James
1be0890f03 0.0.27 2020-07-23 19:16:16 -04:00
James
d45ff316c0 implements intersection observer to mount fields over time 2020-07-23 19:16:01 -04:00
James
d2055141be performance enhancements and render reductions 2020-07-23 17:40:16 -04:00
James
846589e303 0.0.26 2020-07-23 12:18:19 -04:00
James
8efc03b325 0.0.25 2020-07-23 12:18:13 -04:00
James
28d8c10a3e Revert "0.0.24"
This reverts commit f42b2fc670.
2020-07-23 12:15:05 -04:00
Jarrod Flesch
cddba8d9e7 removes internal state from the RTE, updates to the form logic fixed previous issues 2020-07-03 09:27:58 -04:00
Jarrod Flesch
fa02f00503 Merge branch 'master' of github.com:trouble/payload into bugfix/#258-rte-crashing 2020-07-02 17:23:13 -04:00
Jarrod Flesch
9a095f574b adds ExitBreakPlugin, issue has to do with SoftBreakPlugin 2020-07-02 11:44:18 -04:00
672 changed files with 20183 additions and 9907 deletions

View File

@@ -4,7 +4,7 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.js]
[*.{js,ts}]
indent_style = space
indent_size = 2

View File

@@ -1,15 +1,19 @@
module.exports = {
parser: "babel-eslint",
extends: "@trbl",
parser: 'babel-eslint',
extends: '@trbl',
ignorePatterns: [
'/**/*.d.ts'
],
rules: {
"import/no-unresolved": [
'import/no-unresolved': [
2,
{
ignore: [
'payload/config',
'payload/unsanitizedConfig',
]
}
],
},
],
'no-underscore-dangle': 'off',
},
};

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto eol=lf

View File

@@ -25,6 +25,7 @@ jobs:
${{ runner.os }}-build-
${{ runner.os }}-
- run: yarn
- run: yarn test:client
- run: yarn test:int # In-memory db + api tests
env:
CI: true

13
.gitignore vendored
View File

@@ -215,15 +215,16 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
# End of https://www.gitignore.io/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
# Ignores compiled CSS
src/**/*.css
demo**/*.css
dist
# Ignore all uploads
demo/upload
demo/media
demo/files
# Ignore build folder
build
# Ignore built components
components/index.js
components/styles.css

25
.vscode/launch.json vendored
View File

@@ -18,7 +18,30 @@
},
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"port": 9229
"port": 9229,
"skipFiles": [
"<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",

View File

@@ -1,8 +1,21 @@
# Payload
Headless CMS
Headless CMS and application framework
*TODO: More on why to use it and some features*
## Installation
`yarn add @payloadcms/payload` or `npm install @payloadcms/payload`
## Usage
## Development
*TODO: Show basic usage and link to docs*
## Contributing
*TODO: Create Contributing.md*
## License
*TODO: Create License.md*

20
babel.config.js Normal file
View File

@@ -0,0 +1,20 @@
module.exports = {
presets: [
[
require.resolve('@babel/preset-env'),
{
targets: [
'defaults',
'not IE 11',
'not IE_Mob 11',
],
},
],
require.resolve('@babel/preset-react'),
],
plugins: [
require.resolve('@babel/plugin-transform-runtime'),
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-optional-chaining'),
],
};

19
components/forms.js Normal file
View File

@@ -0,0 +1,19 @@
export {
useForm,
useFormFields,
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
View 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
View 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';

View File

@@ -1,9 +0,0 @@
import PageList from '../collections/Page/components/List';
const components = {
pages: {
List: PageList,
},
};
export default components;

View File

@@ -0,0 +1,119 @@
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 '../../../../../../../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 baseClass = 'button-rich-text-button';
const initialFormData = {
style: 'primary',
};
const insertButton = (editor, { href, label, style, newTab = false }) => {
const text = { text: ' ' };
const button = {
type: 'button',
href,
style,
newTab,
label,
children: [
text,
],
};
const nodes = [button, { children: [{ text: '' }] }];
Transforms.insertNodes(editor, nodes);
};
const ToolbarButton = ({ path }) => {
const { open, closeAll } = useModal();
const editor = useSlate();
const handleAddButton = useCallback((fields) => {
const data = reduceFieldsToValues(fields);
insertButton(editor, data);
closeAll();
}, [editor, closeAll]);
const modalSlug = `${path}-add-button`;
return (
<Fragment>
<ElementButton
className={baseClass}
format="button"
onClick={() => open(modalSlug)}
>
Button
</ElementButton>
<Modal
slug={modalSlug}
className={`${baseClass}__modal`}
>
<MinimalTemplate>
<header className={`${baseClass}__header`}>
<h3>Add button</h3>
<Button
buttonStyle="none"
onClick={closeAll}
>
<X />
</Button>
</header>
<Form
onSubmit={handleAddButton}
initialData={initialFormData}
>
<Text
label="Label"
name="label"
required
/>
<Text
label="URL"
name="href"
required
/>
<Select
label="Style"
name="style"
options={[
{
label: 'Primary',
value: 'primary',
},
{
label: 'Secondary',
value: 'secondary',
},
]}
/>
<Checkbox
label="Open in new tab"
name="newTab"
/>
<Submit>
Add button
</Submit>
</Form>
</MinimalTemplate>
</Modal>
</Fragment>
);
};
ToolbarButton.propTypes = {
path: PropTypes.string.isRequired,
};
export default ToolbarButton;

View File

@@ -0,0 +1,33 @@
@import '../../../../../../../scss/vars.scss';
.button-rich-text-button {
.btn {
margin-right: base(1);
}
&__modal {
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;
h3 {
margin: 0;
}
svg {
width: base(1.5);
height: base(1.5);
}
}
}

View File

@@ -0,0 +1,44 @@
import React from 'react';
import PropTypes from 'prop-types';
import './index.scss';
const baseClass = 'rich-text-button';
const ButtonElement = ({ attributes, children, element }) => {
const { style = 'primary', label } = element;
return (
<div
className={baseClass}
contentEditable={false}
>
<span
{...attributes}
className={[
`${baseClass}__button`,
`${baseClass}__button--${style}`,
].join(' ')}
>
{label}
{children}
</span>
</div>
);
};
ButtonElement.defaultProps = {
attributes: {},
children: null,
};
ButtonElement.propTypes = {
attributes: PropTypes.shape({}),
children: PropTypes.node,
element: PropTypes.shape({
style: PropTypes.oneOf(['primary', 'secondary']),
label: PropTypes.string,
}).isRequired,
};
export default ButtonElement;

View File

@@ -0,0 +1,19 @@
@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;
&--primary {
background-color: $color-dark-gray;
color: white;
}
&--secondary {
background-color: $color-light-gray;
}
}

View 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,
],
};

View File

@@ -0,0 +1,10 @@
const withButton = (incomingEditor) => {
const editor = incomingEditor;
const { isVoid } = editor;
editor.isVoid = (element) => (element.type === 'button' ? true : isVoid(element));
return editor;
};
export default withButton;

View File

@@ -0,0 +1,10 @@
import React from 'react';
import { LeafButton } from '../../../../../../../components/rich-text';
const Button = () => (
<LeafButton format="purple-background">
Purple Background
</LeafButton>
);
export default Button;

View File

@@ -0,0 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
const PurpleBackground = ({ attributes, children }) => (
<span
{...attributes}
style={{ backgroundColor: 'purple' }}
>
{children}
</span>
);
PurpleBackground.defaultProps = {
attributes: {},
children: null,
};
PurpleBackground.propTypes = {
attributes: PropTypes.shape({}),
children: PropTypes.node,
};
export default PurpleBackground;

View File

@@ -0,0 +1,8 @@
import button from './Button';
import leaf from './Leaf';
export default {
name: 'purple-background',
button,
leaf,
};

View File

@@ -20,9 +20,17 @@ module.exports = {
admin: () => true,
},
auth: {
tokenExpiration: 7200,
tokenExpiration: 7200, // 2 hours
verify: false,
maxLoginAttempts: 5,
lockTime: 600 * 1000, // lock time in ms
useAPIKey: true,
secureCookie: process.env.NODE_ENV === 'production',
depth: 0,
cookies: {
secure: false,
sameSite: 'Lax',
domain: undefined,
},
},
fields: [
{

View File

@@ -12,6 +12,7 @@ const AllFields = {
},
admin: {
useAsTitle: 'text',
disableScrollOnSuccess: true,
},
preview: (doc, token) => {
if (doc && doc.text) {
@@ -151,11 +152,18 @@ const AllFields = {
label: 'Array Text 1',
type: 'text',
required: true,
}, {
admin: {
width: '50%',
},
},
{
name: 'arrayText2',
label: 'Array Text 2',
type: 'text',
required: true,
admin: {
width: '50%',
},
access: {
read: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => checkRole(['admin'], user),
@@ -171,14 +179,22 @@ const AllFields = {
readOnly: true,
},
},
{
name: 'checkbox',
label: 'Checkbox',
type: 'checkbox',
},
],
},
{
type: 'blocks',
label: 'Blocks Content',
labels: {
singular: 'Block',
plural: 'Blocks',
},
name: 'blocks',
minRows: 2,
singularLabel: 'Block',
blocks: [Email, NumberBlock, Quote, CallToAction],
localized: true,
required: true,
@@ -226,6 +242,32 @@ 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,
};

View File

@@ -16,11 +16,25 @@ module.exports = {
{
name: 'layout',
label: 'Layout Blocks',
singularLabel: 'Block',
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,
},
],
};

View File

@@ -10,6 +10,9 @@ const Code = {
type: 'code',
label: 'Code',
required: true,
admin: {
language: 'js',
},
},
],
};

View File

@@ -1,5 +1,5 @@
import React from 'react';
const Description = () => <div className="description">fake description field</div>
const Description = () => <div className="description">fake description field</div>;
export default Description;

View File

@@ -3,16 +3,14 @@ import PropTypes from 'prop-types';
import './index.scss';
const Filter = ({ onChange, value }) => {
return (
<input
className="custom-description-filter"
type="text"
onChange={e => onChange(e.target.value)}
value={value}
/>
);
};
const Filter = ({ onChange, value }) => (
<input
className="custom-description-filter"
type="text"
onChange={(e) => onChange(e.target.value)}
value={value}
/>
);
Filter.defaultProps = {
value: '',

View File

@@ -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 = (props) => (
<div className="custom-group">
<Group {...props} />
</div>
);
CustomGroup.defaultProps = {
value: '',

View File

@@ -1,18 +1,16 @@
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';
const CustomListView = (props) => {
return (
<div className="custom-list">
<p>This is a custom Pages list view</p>
<p>Sup</p>
<DefaultList {...props} />
</div>
);
};
const CustomListView = (props) => (
<div className="custom-list">
<p>This is a custom Pages list view</p>
<p>Sup</p>
<DefaultList {...props} />
</div>
);
CustomListView.propTypes = {
collection: PropTypes.shape({

View File

@@ -1,4 +1,11 @@
const path = require('path');
const DescriptionField = require('./components/fields/Description/Field').default;
const DescriptionCell = require('./components/fields/Description/Cell').default;
const DescriptionFilter = require('./components/fields/Description/Filter').default;
const NestedArrayField = require('./components/fields/NestedArrayCustomField/Field').default;
const GroupField = require('./components/fields/Group/Field').default;
const NestedGroupField = require('./components/fields/NestedGroupCustomField/Field').default;
const NestedText1Field = require('./components/fields/NestedText1/Field').default;
const ListView = require('./components/views/List').default;
module.exports = {
slug: 'custom-components',
@@ -25,9 +32,9 @@ module.exports = {
localized: true,
admin: {
components: {
field: path.resolve(__dirname, 'components/fields/Description/Field/index.js'),
cell: path.resolve(__dirname, 'components/fields/Description/Cell/index.js'),
filter: path.resolve(__dirname, 'components/fields/Description/Filter/index.js'),
Field: DescriptionField,
Cell: DescriptionCell,
Filter: DescriptionFilter,
},
},
},
@@ -42,7 +49,7 @@ module.exports = {
label: 'Nested Array Custom Field',
admin: {
components: {
field: path.resolve(__dirname, 'components/fields/NestedArrayCustomField/Field/index.js'),
Field: NestedArrayField,
},
},
},
@@ -54,7 +61,7 @@ module.exports = {
type: 'group',
admin: {
components: {
field: path.resolve(__dirname, 'components/fields/Group/Field/index.js'),
Field: GroupField,
},
},
fields: [
@@ -64,7 +71,7 @@ module.exports = {
label: 'Nested Group Custom Field',
admin: {
components: {
field: path.resolve(__dirname, 'components/fields/NestedGroupCustomField/Field/index.js'),
Field: NestedGroupField,
},
},
},
@@ -79,7 +86,7 @@ module.exports = {
type: 'text',
admin: {
components: {
field: path.resolve(__dirname, 'components/fields/NestedText1/Field/index.js'),
Field: NestedText1Field,
},
},
}, {
@@ -95,7 +102,7 @@ module.exports = {
useAsTitle: 'title',
components: {
views: {
List: path.resolve(__dirname, 'components/views/List/index.js'),
List: ListView,
},
},
},

View File

@@ -0,0 +1,272 @@
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');
const DefaultValueTest = {
slug: 'default-value-test',
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',
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',
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',
default: true,
},
],
},
{
type: 'blocks',
label: 'Blocks Content',
name: 'blocks',
labels: {
singular: 'Block',
plural: 'Blocks',
},
blocks: [Email, NumberBlock, Quote, CallToAction],
localized: true,
},
{
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: 'sooo riiiiiiiich',
},
],
timestamps: true,
};
module.exports = DefaultValueTest;

View File

@@ -0,0 +1,283 @@
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');
const DefaultValues = {
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',
default: true,
},
],
},
{
type: 'blocks',
label: 'Blocks Content',
name: 'blocks',
labels: {
singular: 'Block',
plural: 'Blocks',
},
blocks: [Email, NumberBlock, Quote, CallToAction],
localized: true,
},
{
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,
};
module.exports = DefaultValues;

View File

@@ -1,4 +1,3 @@
const path = require('path');
const checkRole = require('../access/checkRole');
const access = ({ req: { user } }) => {
@@ -15,6 +14,8 @@ const access = ({ req: { user } }) => {
},
};
}
return false;
};
module.exports = {
@@ -25,7 +26,7 @@ module.exports = {
},
upload: {
staticURL: '/files',
staticDir: path.resolve(__dirname, '../files'),
staticDir: './files',
},
access: {
create: () => true,

View File

@@ -15,14 +15,6 @@ module.exports = {
delete: () => true,
},
hooks: {
beforeCreate: [
(operation) => {
if (operation.req.headers.hook === 'beforeCreate') {
operation.req.body.description += '-beforeCreateSuffix';
}
return operation.data;
},
],
beforeRead: [
(operation) => {
if (operation.req.headers.hook === 'beforeRead') {
@@ -30,10 +22,10 @@ module.exports = {
}
},
],
beforeUpdate: [
beforeChange: [
(operation) => {
if (operation.req.headers.hook === 'beforeUpdate') {
operation.req.body.description += '-beforeUpdateSuffix';
if (operation.req.headers.hook === 'beforeChange') {
operation.req.body.description += '-beforeChangeSuffix';
}
return operation.data;
},
@@ -46,14 +38,6 @@ module.exports = {
}
},
],
afterCreate: [
(operation) => {
if (operation.req.headers.hook === 'afterCreate') {
operation.doc.afterCreateHook = true;
}
return operation.doc;
},
],
afterRead: [
(operation) => {
const { doc } = operation;
@@ -62,10 +46,10 @@ module.exports = {
return doc;
},
],
afterUpdate: [
afterChange: [
(operation) => {
if (operation.req.headers.hook === 'afterUpdate') {
operation.doc.afterUpdateHook = true;
if (operation.req.headers.hook === 'afterChange') {
operation.doc.afterChangeHook = true;
}
return operation.doc;
},

View File

@@ -0,0 +1,36 @@
const LocalOperations = {
slug: 'local-operations',
labels: {
singular: 'Local Operation',
plural: 'Local Operations',
},
hooks: {
afterRead: [
async ({ req, doc }) => {
const formattedData = { ...doc };
const localizedPosts = await req.payload.find({
collection: 'localized-posts',
});
const blocksGlobal = await req.payload.findGlobal({
global: 'blocks-global',
});
formattedData.localizedPosts = localizedPosts;
formattedData.blocksGlobal = blocksGlobal;
return formattedData;
},
],
},
fields: [
{
name: 'title',
type: 'text',
label: 'title',
required: true,
},
],
};
module.exports = LocalOperations;

View File

@@ -11,12 +11,13 @@ module.exports = {
'priority',
'createdAt',
],
enableRichTextRelationship: true,
},
access: {
read: () => true,
},
preview: (doc, token) => {
if (doc.title) {
if (doc && doc.title) {
return `http://localhost:3000/posts/${doc.title.value}?preview=true&token=${token}`;
}
@@ -32,6 +33,12 @@ module.exports = {
unique: true,
localized: true,
},
{
name: 'summary',
label: 'Summary',
type: 'text',
index: true,
},
{
name: 'description',
label: 'Description',

View File

@@ -1,4 +1,3 @@
const path = require('path');
const checkRole = require('../access/checkRole');
module.exports = {
@@ -10,9 +9,12 @@ module.exports = {
access: {
read: () => true,
},
admin: {
enableRichTextRelationship: true,
},
upload: {
staticURL: '/media',
staticDir: path.resolve(__dirname, '../media'),
staticDir: './media',
adminThumbnail: 'mobile',
imageSizes: [
{
@@ -41,11 +43,6 @@ module.exports = {
type: 'text',
required: true,
localized: true,
hooks: {
afterRead: [
({ value }) => `${value} alt`,
],
},
},
{
name: 'sizes',

View File

@@ -32,7 +32,15 @@ module.exports = {
},
auth: {
tokenExpiration: 300,
secureCookie: process.env.NODE_ENV === 'production',
verify: true,
maxLoginAttempts: 5,
lockTime: 600 * 1000, // lock time in ms
generateVerificationUrl: (req, token) => `http://localhost:3000/api/verify?token=${token}`,
cookies: {
secure: process.env.NODE_ENV === 'production',
sameSite: 'Lax',
domain: undefined,
},
},
fields: [
{

View File

@@ -1,3 +1,6 @@
const Button = require('../client/components/richText/elements/Button').default;
const PurpleBackground = require('../client/components/richText/leaves/PurpleBackground').default;
const RichText = {
slug: 'rich-text',
labels: {
@@ -6,12 +9,27 @@ const RichText = {
},
fields: [
{
name: 'richText',
name: 'defaultRichText',
type: 'richText',
label: 'Rich Text',
label: 'Default Rich Text',
required: true,
disabledElements: [],
disabledMarks: [],
},
{
name: 'customRichText',
type: 'richText',
label: 'Customized Rich Text',
required: true,
admin: {
elements: [
'h2',
'h3',
Button,
],
leaves: [
'bold',
PurpleBackground,
],
},
},
],
};

View File

@@ -0,0 +1,43 @@
const Select = {
slug: 'select',
labels: {
singular: 'Select',
plural: 'Selects',
},
fields: [
{
name: 'Select',
type: 'select',
options: [{
value: 'one',
label: 'One',
}, {
value: 'two',
label: 'Two',
}, {
value: 'three',
label: 'Three',
}],
label: 'Select From',
required: true,
},
{
name: 'Radio',
type: 'radio',
options: [{
value: 'one',
label: 'One',
}, {
value: 'two',
label: 'Two',
}, {
value: 'three',
label: 'Three',
}],
label: 'Choose From',
required: true,
},
],
};
module.exports = Select;

15
demo/custom-index.html Normal file
View File

@@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="application-name" content="My Payload Application" />
</head>
<body>
<div id="app"></div>
<div id="portal"></div>
</body>
</html>

View File

@@ -1,4 +1,3 @@
const path = require('path');
const Admin = require('./collections/Admin');
const AllFields = require('./collections/AllFields');
const Code = require('./collections/Code');
@@ -6,10 +5,12 @@ const Conditions = require('./collections/Conditions');
const CustomComponents = require('./collections/CustomComponents');
const File = require('./collections/File');
const Blocks = require('./collections/Blocks');
const DefaultValues = require('./collections/DefaultValues');
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');
@@ -17,6 +18,7 @@ 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');
@@ -27,13 +29,24 @@ 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: {
layout: {
// Sidebar: path.resolve(__dirname, 'client/components/layout/Sidebar/index.js'),
},
// Nav: () => (
// <div>Hello</div>
// ),
},
},
email: {
transport: 'mock',
fromName: 'Payload',
fromAddress: 'hello@payloadcms.com',
},
collections: [
Admin,
AllFields,
@@ -41,11 +54,13 @@ module.exports = {
Conditions,
CustomComponents,
File,
DefaultValues,
Blocks,
HiddenFields,
Hooks,
Localized,
LocalizedArray,
LocalOperations,
Media,
NestedArrays,
Preview,
@@ -53,6 +68,7 @@ module.exports = {
RelationshipA,
RelationshipB,
RichText,
Select,
StrictPolicies,
Validations,
],
@@ -63,7 +79,16 @@ module.exports = {
],
cookiePrefix: 'payload',
serverURL: 'http://localhost:3000',
cors: ['http://localhost', 'http://localhost:8080', 'http://localhost:8081'],
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',
@@ -73,12 +98,21 @@ module.exports = {
defaultDepth: 2,
compression: {},
paths: {
scss: path.resolve(__dirname, 'client/scss/overrides.scss'),
scss: 'client/scss/overrides.scss',
},
graphQL: {
maxComplexity: 1000,
mutations: {},
queries: {},
disablePlaygroundInProduction: true,
},
rateLimit: {
window: 15 * 60 * 100,
max: 100,
trustProxy: true,
skip: (req) => req.ip === '127.0.0.1',
},
maxDepth: 10,
localization: {
locales: [
'en',
@@ -87,10 +121,14 @@ module.exports = {
defaultLocale: 'en',
fallback: true,
},
productionGraphQLPlayground: false,
hooks: {
afterError: () => {
console.error('global error config handler');
afterError: (err) => {
console.error('global error config handler', err);
},
},
upload: {
limits: {
fileSize: 10000000, // 10MB
},
},
webpack: (config) => config,

View File

@@ -1,27 +1,26 @@
/* eslint-disable no-console */
const express = require('express');
const path = require('path');
const Payload = require('../src');
const payload = require('../src');
const logger = require('../src/utilities/logger')();
const expressApp = express();
expressApp.use('/static', express.static(path.resolve(__dirname, 'client/static')));
const payload = new Payload({
email: {
provider: 'mock',
},
payload.init({
secret: 'SECRET_KEY',
mongoURL: 'mongodb://localhost/payload',
express: expressApp,
onInit: () => {
console.log('Payload is initialized');
logger.info('Payload is initialized');
// console.log('Payload is initialized');
},
});
const externalRouter = express.Router();
externalRouter.use(payload.authenticate());
externalRouter.use(payload.authenticate);
externalRouter.get('/', (req, res) => {
if (req.user) {
@@ -33,17 +32,11 @@ externalRouter.get('/', (req, res) => {
expressApp.use('/external-route', externalRouter);
exports.payload = payload;
exports.start = (cb) => {
const server = expressApp.listen(3000, async () => {
console.log(`listening on ${3000}...`);
if (cb) cb();
logger.info(`listening on ${3000}...`);
const creds = await payload.getMockEmailCredentials();
console.log(`Mock email account username: ${creds.user}`);
console.log(`Mock email account password: ${creds.pass}`);
console.log(`Log in to mock email provider at ${creds.web}`);
if (cb) cb();
});
return server;

View File

@@ -0,0 +1,7 @@
---
title: Access Control Config
label: Config
order: 10
---
Talk about how to write access control.

View File

@@ -0,0 +1,7 @@
---
title: Access Control Examples
label: Examples
order: 20
---
Show examples of how to write access control functions.

View 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.

View 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)

View 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.

View File

@@ -0,0 +1,7 @@
---
title: Authentication Security
label: Security
order: 20
---
Talk about how Payload securely authenticates here.

View 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

View 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.

View File

@@ -0,0 +1,7 @@
---
title: Block Configs
label: Blocks
order: 40
---
Talk about how to write block configs here.

View File

@@ -0,0 +1,7 @@
---
title: Collection Configs
label: Collections
order: 20
---
Talk about how to write collection configs here.

View File

@@ -0,0 +1,7 @@
---
title: Global Configs
label: Globals
order: 30
---
Talk about how to write Globals configs here.

View 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
View 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
View 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

View 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
View 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
}
```

View File

@@ -0,0 +1,7 @@
---
title: Configure Email
label: Configure Email
order: 30
---
TODO: Configure SendGrid or similar

320
docs/Hooks/config.mdx Normal file
View File

@@ -0,0 +1,320 @@
---
title: Hooks Config
label: Config
order: 10
---
<Banner type="info">
Hooks allow intervention before or after any internal operation.
Payload has extensive support for hooks, at both the document-level and field-level.
</Banner>
## Hook Types
- [Collection Hooks](#collection-hooks)
- [Field Hooks](#field-hooks)
- [Error Hook](#error-hook)
## Collection Hooks
Collection can be executed at any point in the modification or retrieval of a collection.
Collection Hooks available:
_TODO: Fix anchor links_
- [beforeOperation](#beforeOperation)
- [beforeValidate](#beforeValidate)
- [beforeChange](#beforeChange)
- [afterChange](#afterChange)
- [beforeRead](#beforeRead)
- [afterRead](#afterRead)
- [beforeDelete](#beforeDelete)
- [afterDelete](#afterDelete)
### Usage
Configuration of collection hooks is done under a collection config in `payload.config.js`. They can either be created in-line or required from a separate file. Each hook is an array of functions to be run.
_TODO: Talk about async vs synchronous and concurrency_
```js
// Collection config
module.exports = {
slug: 'public-user',
fields: [
{ name: 'name', label: 'Name', type: 'text'},
]
hooks: {
// Before All Operations
beforeOperation: [(args) => {...}],
// Create and Update Operations
beforeValidate: [(args) => {...}],
beforeChange: [(args) => {...}],
afterChange: [(args) => {...}],
// Read Operations
beforeRead: [(args) => {...}],
afterRead: [(args) => {...}],
// Delete Operations
beforeDelete: [(args) => {...}],
afterDelete: [(args) => {...}],
// Login Operations
beforeLogin: [(args) => {...}],
afterLogin: [(args) => {...}],
// After error
afterError: [(args) => {...}],
}
}
```
Each hook is an array of functions allowing for multiple to be combined as desired.
Configuration of hooks should be done in your `payload.config.js`
#### beforeOperation
Runs before any operation
```js
const beforeOperationHook = ({
args, // Original arguments passed into the operation
operation, // name of the operation
}) => {...}
```
Available Operations: `create`, `read`, `update`, `delete`, `refresh`, `forgotPassword`
#### beforeValidate
Runs before the `create` and `update` operations.
```js
const beforeValidateHook = ({
data, // incoming document data
req, // full express request
operation, // name of the operation ie. 'create', 'update'
originalDoc, // original document
}) => {...}
```
#### beforeChange
Runs before `create` and `update` operations, after validation.
```js
const beforeChangeHook = ({
data, // incoming document data
req, // full express request
operation, // name of the operation ie. 'create', 'update'
originalDoc, // original document
}) => {...}
```
#### afterChange
Runs after `create` and `update` operations.
```js
const afterChangeHook = ({
doc, // full document data
req, // full express request
operation, // name of the operation ie. 'create', 'update'
}) => {...}
```
#### beforeRead
Runs before `find` and `findByID` operations.
```js
const beforeReadHook = ({
doc, // full document data
req, // full express request
query, // JSON formatted query
}) => {...}
```
#### afterRead
Runs after `find` and `findByID` operations.
```js
const afterReadHook = ({
doc, // full document data
req, // full express request
query, // JSON formatted query
}) => {...}
```
#### beforeDelete
Runs before `delete` operation
```js
const beforeDeleteHook = ({
req, // full express request
id, // id of document to delete
}) => {...}
```
#### afterDelete
Runs after `delete` operation
```js
const afterDeleteHook = ({
req, // full express request
id, // id of document to delete
doc, // deleted document
}) => {...}
```
#### beforeLogin
Runs before `login` operation
```js
const beforeLoginHook = ({
req, // full express request
}) => {...}
```
#### afterLogin
Runs after `login` operation
```js
const afterLoginHook = ({
req, // full express request
user, // user being logged in
token, // user token
}) => {...}
```
#### afterError
Runs after an error occurs
_TODO: example usage_
## Field Hooks
Field can be executed at any point in the modification or retrieval of a collection field.
Field Hooks available:
- `beforeValidate`
- `beforeChange`
- `afterChange`
- `afterRead`
### Usage
```js
// Collection config
module.exports = {
slug: 'public-user',
fields: [
{
name: 'name',
label: 'Name',
type: 'text',
hooks: {
// Create and Update Operations
beforeValidate: [(args) => {...}],
beforeChange: [(args) => {...}],
afterChange: [(args) => {...}],
// Read Operations
afterRead: [(args) => {...}],
}
},
],
}
```
#### beforeValidate
Runs before the `create` and `update` operations.
```js
const beforeValidateHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
#### beforeChange
Runs before the `create` and `update` operations, after validation.
```js
const beforeChangeHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
#### afterChange
Runs after `create` and `update` operations
```js
const afterChangeHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
#### afterRead
Runs after result as been retrieved from database
```js
const beforeChangeHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
## Hook Lifecycle
Hooks execute in the following order in relation to operations
`beforeOperation` is a special hook that runs _before all operations_.
### Create/Update Lifecycle
1. `beforeValidate` Field Hooks
2. `beforeValidate` Collection Hooks
3. Validate operation
4. `beforeChange` Field Hooks
5. `beforeChange` Collection Hooks
6. Create/Update against database
7. `afterChange` Field Hooks
8. `afterChange` Collection Hooks
### Find Lifecycle
1. `beforeRead` Collection Hooks
2. Find against database
3. `afterRead` Field Hooks
4. `afterRead` Collection Hooks

64
docs/Hooks/examples.mdx Normal file
View File

@@ -0,0 +1,64 @@
---
title: Hooks Examples
label: Examples
order: 20
---
### Collection Hooks
#### Set createdBy and lastModifiedBy
```js
beforeChange: [
({ req, operation }) => {
if (req.user && req.body) {
if (operation === 'create') {
req.body.createdBy = req.user.id;
}
req.body.lastModifiedBy = req.user.id;
}
}
]
```
_NOTE: createdBy and lastModifiedBy must be fields on the collection_
#### Use Local Payload API
Queries a separate collection and appends to returned result
```js
afterRead: [
async ({ req, doc }) => {
const formattedData = { ...doc };
const posts = await req.payload.find({
collection: 'posts',
});
formattedData.posts = posts;
return formattedData;
},
],
```
#### Read Request Header
```js
beforeRead: [
({ req }) => {
if (req.headers.specialheader === 'special') {
// Do something...
}
},
],
```
### Field Hooks
#### Kebab-case Formatter
```js
beforeValidate: [
({ value }) => val.replace(/ /g, '-').toLowerCase();
]
```

View File

@@ -0,0 +1,11 @@
---
title: Server-Side Operations
label: Overview
order: 10
---
Talk about how to run server-side operations.
- Access control
- Providing a user

View File

@@ -0,0 +1,11 @@
---
title: Production Deployment
label: Deployment
order: 10
---
Talk about how to deploy Payload here.
- DigitalOcean
- If no file storage, Heroku
- If file storage, need Heroku extensions

View File

@@ -0,0 +1,10 @@
---
title: Production Security Measures
label: Security
order: 20
---
- Rate limiting
- GraphQL Complexity
- Limits
- Max Depth

119
docs/REST-API/config.mdx Normal file
View File

@@ -0,0 +1,119 @@
---
title: REST API Overview
label: Overview
order: 10
---
_TODO: Middleware_
<Banner type="info">
The Payload REST API is created using properties in each collection's config
</Banner>
Access to each collection is mounted on the API route using the collection's `slug` value. For example if a collection's slug is `users`, access to that collection will be mounted on `/api/users`.
Basic CRUD operations are automatically made available:
## Endpoints
### Collections
| Method | Path | Description |
| :------- | :---------------------- | :----------------------------------- |
| `GET` | `/api/{collection}` | Get all {collection} documents |
| `GET` | `/api/{collection}/:id` | Get a specific {collection} document |
| `POST` | `/api/{collection}` | Create a {collection} document |
| `DELETE` | `/api/{collection}/:id` | Delete a {collection} document |
| `PUT` | `/api/{collection}/:id` | Update a {collection} document |
### Globals
| Method | Path | Description |
| :------- | :---------------------- | :--------------------- |
| `GET` | `/api/globals/{global}` | Get {global} |
| `POST` | `/api/globals/{global}` | Create/Update {global} |
| `DELETE` | `/api/globals/{global}` | Delete a {global} |
NOTE: The `/api` prefix can be customized in the [main Payload configuration](../Configuration/main)
## Responses
### Collections
All collection queries return metadata
#### Example Response
Collection Query
```js
{
// Document Array // highlight-line
"docs": [
{
"title": "Page Title",
"description": "Some description text",
"priority": 1,
"createdAt": "2020-10-17T01:19:29.858Z",
"updatedAt": "2020-10-17T01:19:29.858Z",
"id": "5f8a46a1dd05db75c3c64760"
}
],
// Metadata // highlight-line
"totalDocs": 6,
"limit": 1,
"totalPages": 6,
"page": 1,
"pagingCounter": 1,
"hasPrevPage": false,
"hasNextPage": true,
"prevPage": null,
"nextPage": 2
}
```
Documents queried by id and globals will return a single JSON document, no metadata
| Property | Description |
| :------------ | :--------------------------------------------------------- |
| docs | Array of documents in the {collection} |
| totalDocs | Total available documents of {collection} |
| limit | Limit query parameter. Defaults to `10`, can be configured |
| totalPages | Total pages available, based upon the `limit` queried for |
| page | Current page |
| pagingCounter | `number` for the first doc on the current page |
| hasPrevPage | `true/false` if previous page exists |
| hasNextPage | `true/false` if next page exists |
| prevPage | `number` of previous page. `null` if doesn't exist. |
| nextPage | `number` of next page. `null` if doesn't exist. |
## Query Parameters
| param | description | example |
| :------ | :---------------------------------------------------------------------------------------- | :------------------------------- |
| `limit` | Limits the number of documents returned | `?limit=3` |
| `page` | Get specific page number | `?page=2` |
| `sort` | Sort on a specific field. Use field name for ascending. Prefix with `-` for descending | `?sort=age`, `?sort=-age` |
| `depth` | Controls how deep in JSON structure to return in the query. _Follows relationship fields_ | `?depth=3` |
| `where` | Exposes many logical operators. _In-depth documentation below_ | `?where[property][equals]=value` |
### Where
Query on specific collection field values
| operator | description | example |
| :------------------- | :-------------------------------------------------- | :------------------------------------------- |
| `equals` | | `?where[property][equals]=value` |
| `not_equals` | | `?where[property][not_equals]=value` |
| `greater_than` | | `?where[property][greater_than]=value` |
| `greater_than_equal` | | `?where[property][greater_than_equal]=value` |
| `less_than` | | `?where[property][less_than]=value` |
| `less_than_equal` | | `?where[property][less_than_equal]=value` |
| `like` | Partial match against property | `?where[property][like]=value` |
| `in` | Query for values in a comma-delimited list | `?where[property][in]=value1,value2` |
| `not_in` | Query for values _not in_ in a comma-delimited list | `?where[property][not_in]=value1,value2` |
| `exists` | Query for existence of a property | `?where[property][exists]=true` |
#### Complex Examples
_TODO: Complex Examples_

16
docs/Upload/config.mdx Normal file
View File

@@ -0,0 +1,16 @@
---
title: Upload Config
label: Config
order: 10
---
Talk about how to configure uploads here.
Need to cover:
1. Can have multiple collections
1. Static directory
1. How to upload (multipart/form-data)
1. Uploading is REST-only
1. Access control
1. Image sizes

View File

@@ -0,0 +1,39 @@
---
title: Payload Concepts
label: Concepts
order: 20
---
Payload is based around a small and intuitive set of concepts. Before starting to work with Payload, it's a good idea to familiarize yourself with the following:
### Config
<Banner type="info">
The Payload config is where you configure everything that Payload does.
</Banner>
By default, the Payload config lives in the root folder of your code and is named `payload.config.js`, but you can customize where you store it. The `config` is plain old JavaScript, meaning you can write full JavaScript functions and even full React components right into your config.
### Collections
<Banner type="info">
A Collection represents a type of content that Payload will store and can contain many documents.
</Banner>
Payload Collections are defined through Each Collection will map one-to-one with a MongoDB collection automatically based on fields that you define. You can have as many Collections as you need. It's often best practice to write your Collections in separate files,
### Globals
<Banner type="info">
A Global is a "one-off" piece of content that is perfect for storing navigational structures, themes, top-level meta data, and more.
</Banner>
You can define as many Collections as you need. On each Collection, you can specify the shape of your data through Fields.
### Fields
<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.
</Banner>
Payload comes with [many different types](../fields/overview) of Fields that give you a ton of flexibility while designing your API. Each Field type has its own potential properties that allow you to customize how they work.

View File

@@ -0,0 +1,94 @@
---
title: Installation
label: Installation
order: 30
---
### Requirements
Payload requires the following software:
- Yarn or NPM
- NodeJS version 10+
- A Mongo Database
- Express
Once you are sure that you have all of these dependencies, you can `yarn add payload` or `npm install --save payload` at the root of your project folder.
The first step is writing a baseline config. The simplest config contains the following:
```
export default {
serverURL: 'http://localhost:3000',
};
```
Create a new `payload.config.js` file in the root of your project and write the above code into it. This file fully supports ES6.
Although this is just the bare minimum config, there are *many* more options that you can control here. To reference the full config and all of its options, [click here](/docs/configuration/main).
### Server
Now that you've got a baseline Payload config, it's time to initialize Payload. It requires an Express server that you provide, so if you're not familiar with how to set up a baseline Express server, please read up on exactly what Express is and why to use it. Express' own [Documentation](https://expressjs.com/en/starter/hello-world.html) is a good place to start. Otherwise, follow along below for how to build your own Express server to use with Payload.
1. Run `yarn add express`
1. Create a new `server.js` file in the root folder of your app
1. Add the following code to `server.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 server doesn't do anything just yet. But, after you have this in place, it's time to initialize Payload. Payload is initialized via its `init()` method, which accepts a small set of arguments to tell it how to operate. For a full list of `init` arguments, please consult the [main configuration](/docs/configuration/main#init) docs.
To initialize Payload, update your `server.js` file with the following code:
```
const express = require('express');
const payload = require('payload');
const app = express();
payload.init({
secret: 'SECRET_KEY',
mongoURL: 'mongodb://localhost/payload',
express: app,
})
app.listen(3000, async () => {
console.log('Express is now listening for incoming connections on port 3000.')
});
```
As you can see above, the required arguments to the `init` function are as follows:
##### `secret`
This is a secure string that will be used to authenticate with Payload. It can be random but should be at least 14 characters and be very difficult to guess. Often, it's smart to store this value in an `env` and set different values for each of your environments (ocal, stage, prod, etc).
##### `mongoURL`
This is a fully qualified MongoDB connection string that points to your Mongo database. If you don't have Mongo installed locally, you can [follow these steps for Mac OSX](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/) and [these steps](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/) for Windows 10. If you want to use a local database and you know you have MongoDB installed locally, a typical connection string will look like this:
`mongodb://localhost/payload`
In contrast to running Mongo locally, a popular option is to sign up for a free [MongoDB Atlas account](https://www.mongodb.com/cloud/atlas), which is a fully hosted and cloud-based installation of Mongo that you don't need to ever worry about.
##### `express`
This is your Express app as shown above. Payload will tie into your existing `app` and scope all of its functionalities to sub-routers. By default, Payload will add an `/admin` router and an `/api` router, but you can customize these paths.
### Test it out
After you've gotten this far, it's time to boot up Payload. At the command line, run `yarn` or `npm install` and then `node server.js` in your application's folder to start up your app and initialize Payload.
After it starts, you can go to `http://localhost:3000/admin` to create your first Payload user!

View File

@@ -0,0 +1,53 @@
---
title: What is Payload?
label: What is Payload?
order: 10
---
<Banner type="success">
Payload is a headless CMS and application framework. Its meant to provide a massive boost to your development process, but importantly, stay out of your way as your apps get more complex.
</Banner>
Out of the box, Payload gives you a lot of the things that you often need when developing a new website, web app, or native app:
- A Mongo database to store your data
- A way to store, retrieve, and manipulate data of any shape via full REST and GraphQL APIs
- Authentication—complete with commonly required functionality like registration, email verification, login, & password reset
- Deep access control to your data, based on document or field-level functions
- File storage and access control
- A beautiful admin UI thats generated specifically to suit your data
## What does "headless" mean?
A headless CMS is a system that sticks to what it's good at—managing content. It concentrates solely on granting administrators an effective way to author and maintain content, but doesn't control how and where that content is used.
In this way, the CMS can ensure that its content editing experience is highly polished and effective while avoiding placing creative constraints on designers or restricting development teams. In contrast, traditional content management systems bind the presentation of your content to the storage of your content and severely limit the creativity, development and usability of the content that they manage.
At this point this concept is [widely](https://en.wikipedia.org/wiki/Headless_content_management_system) [discussed](https://css-tricks.com/what-is-a-headless-cms/) online, and for good reason. The web has become more complicated and with complexity comes the demand for developers to better structure their code. The rise of interface libraries like React and Vue are now the de-facto standard for building modern applications and traditional content management systems are often not designed to make use of them.
### Why Payload?
The team behind Payload has been building websites and apps with existing content management systems and application frameworks for over a decade. We know what works and what doesn't about each of the existing solutions, and to this day have found no silver bullet solution.
**We believe that a CMS should be:**
- Cost-effective and should save time and effort
- Intuitive for developers and content authors alike
- Self-hosted however and wherever the application specifies
- Designed in code but used with no coding experience
- Blazing fast
- Secure
- Fully flexible and extensible
Payload is our silver bullet solution. It represents over two years of passionate development and brings everything we need when we build new apps and websites:
- A beautiful, dynamic, customizable admin UI
- Extensible and reusable authentication
- Content localization
- Local file storage
- Extremely flexible access control
- Field conditional logic
- Block-based layout building
- Array field type(s)
- Security
- and much more

View File

@@ -1,5 +1,6 @@
const { APIError } = require('./src/errors');
const { APIError, Forbidden } = require('./src/errors');
module.exports = {
APIError,
Forbidden,
};

View File

@@ -1,2 +0,0 @@
export { default as Group } from './src/client/components/forms/field-types/Group';
export { default as Select } from './src/client/components/forms/field-types/Select';

View File

@@ -1,2 +0,0 @@
export { default as useFieldType } from './src/client/components/forms/useFieldType';
export { useForm } from './src/client/components/forms/Form/context';

View File

@@ -1,6 +1,15 @@
module.exports = {
verbose: true,
testEnvironment: 'node',
globalSetup: '<rootDir>/src/tests/globalSetup.js',
globalTeardown: '<rootDir>/src/tests/globalTeardown.js',
globalSetup: '<rootDir>/tests/api/globalSetup.js',
globalTeardown: '<rootDir>/tests/api/globalTeardown.js',
testPathIgnorePatterns: [
'node_modules',
'src/admin/*',
],
testTimeout: 15000,
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/mocks/fileMock.js',
'\\.(css|scss)$': '<rootDir>/src/mocks/emptyModule.js',
},
};

10
jest.react.config.js Normal file
View File

@@ -0,0 +1,10 @@
module.exports = {
verbose: true,
testTimeout: 15000,
testRegex: '(/src/admin/.*\\.(test|spec))\\.[jt]sx?$',
setupFilesAfterEnv: ['<rootDir>/tests/client/globalSetup.js'],
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/mocks/fileMock.js',
'\\.(css|scss)$': '<rootDir>/src/mocks/emptyModule.js',
},
};

3
logger.js Normal file
View File

@@ -0,0 +1,3 @@
const logger = require('./src/utilities/logger');
module.exports = logger;

View File

@@ -1,40 +1,49 @@
{
"name": "@payloadcms/payload",
"version": "0.0.24",
"version": "0.0.141",
"description": "CMS and Application Framework",
"license": "ISC",
"author": "Payload CMS LLC",
"main": "index.js",
"typings": "types/index.d.ts",
"sideEffects": false,
"bin": {
"payload": "./src/bin/index.js"
},
"scripts": {
"build:components": "webpack --config src/webpack/components.config.js",
"build": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js node src/bin/build",
"build:analyze": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js PAYLOAD_ANALYZE_BUNDLE=true node src/bin/build",
"cov": "npm run core:build && node ./node_modules/jest/bin/jest.js src/tests --coverage",
"debug": "nodemon --inspect demo/server.js",
"debug": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js nodemon --inspect demo/server.js",
"debug:test:int": "node --inspect-brk node_modules/.bin/jest --runInBand",
"dev": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js nodemon demo/server.js",
"lint": "eslint .",
"test:int": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js NODE_ENV=test jest --forceExit --runInBand",
"test:unit": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js NODE_ENV=test jest"
"test": "yarn test:int && yarn test:client",
"test:int": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js NODE_ENV=test DISABLE_LOGGING=true jest --forceExit --runInBand",
"test:client": "cross-env PAYLOAD_CONFIG_PATH=demo/payload.config.js NODE_ENV=test jest --config=jest.react.config.js"
},
"dependencies": {
"@babel/core": "^7.8.3",
"@babel/core": "^7.11.6",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.8.3",
"@babel/preset-react": "^7.8.3",
"@babel/runtime": "^7.8.4",
"@babel/register": "^7.11.5",
"@babel/runtime": "^7.11.2",
"@date-io/date-fns": "^1.3.13",
"@faceless-ui/collapsibles": "^0.1.0",
"@faceless-ui/modal": "^1.0.4",
"@faceless-ui/scroll-info": "^1.1.1",
"@faceless-ui/window-info": "^1.2.2",
"@udecode/slate-plugins": "^0.60.0",
"@udecode/slate-plugins": "^0.64.3",
"ajv": "^6.12.6",
"async-some": "^1.0.2",
"autoprefixer": "^9.7.4",
"babel-core": "^7.0.0-bridge.0",
"babel-loader": "^8.0.6",
"babel-jest": "^26.3.0",
"babel-loader": "^8.1.0",
"babel-plugin-add-module-exports": "^1.0.4",
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"connect-history-api-fallback": "^1.6.0",
@@ -42,46 +51,54 @@
"date-fns": "^2.14.0",
"deepmerge": "^4.2.2",
"dotenv": "^6.0.0",
"dotenv-webpack": "^1.8.0",
"es6-promise": "^4.2.8",
"express": "^4.17.1",
"express-fileupload": "^1.1.6",
"express-graphql": "^0.9.0",
"express-rate-limit": "^5.1.3",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"falsey": "^1.0.0",
"file-loader": "^1.1.11",
"flatley": "^5.2.0",
"graphql": "^15.0.0",
"graphql-date": "^1.0.3",
"graphql-playground-middleware-express": "^1.7.14",
"graphql-query-complexity": "^0.7.0",
"graphql-scalars": "^1.4.0",
"graphql-type-json": "^0.3.1",
"html-webpack-plugin": "^3.2.0",
"http-status": "^1.4.2",
"image-size": "^0.7.5",
"ignore-styles": "^5.0.1",
"is-hotkey": "^0.1.6",
"is-url": "^1.2.4",
"isomorphic-fetch": "^2.2.1",
"isomorphic-style-loader": "^5.1.0",
"jest": "^25.3.0",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^3.0.0",
"method-override": "^3.0.0",
"micro-memoize": "^4.0.9",
"mini-css-extract-plugin": "^1.0.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"mkdirp": "^1.0.4",
"mongodb-memory-server": "^6.5.2",
"mongoose": "^5.8.9",
"mongoose-hidden": "^1.8.1",
"mongoose-paginate-v2": "^1.3.6",
"node-sass": "^4.13.1",
"node-sass-chokidar": "^1.4.0",
"node-sass": "^4.14.1",
"nodemailer": "^6.4.2",
"object-to-formdata": "^3.0.9",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"passport": "^0.4.1",
"passport-anonymous": "^1.0.1",
"passport-headerapikey": "^1.2.1",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"passport-local-mongoose": "^6.0.1",
"postcss-flexbugs-fixes": "^3.3.1",
"postcss-loader": "^2.1.6",
"postcss-preset-env": "6.0.6",
"pino": "^6.4.1",
"pino-pretty": "^4.1.0",
"postcss-loader": "^4.0.4",
"postcss-preset-env": "^6.7.0",
"prismjs": "^1.21.0",
"probe-image-size": "^5.0.0",
"prop-types": "^15.7.2",
"qs": "^6.9.1",
"qs-middleware": "^1.0.3",
@@ -91,43 +108,54 @@
"react-datepicker": "^2.13.0",
"react-document-meta": "^3.0.0-beta.2",
"react-dom": "^16.13.1",
"react-hook-form": "^5.7.2",
"react-redux": "^7.2.0",
"react-helmet": "^6.1.0",
"react-router-dom": "^5.1.2",
"react-router-navigation-prompt": "^1.8.11",
"react-select": "^3.0.8",
"react-simple-code-editor": "^0.11.0",
"react-toastify": "^6.1.0",
"sanitize-filename": "^1.6.3",
"sass": "^1.27.0",
"sass-loader": "7.1.0",
"sharp": "^0.25.2",
"slate": "^0.58.3",
"slate": "^0.58.4",
"slate-history": "^0.58.3",
"slate-hyperscript": "^0.58.3",
"slate-react": "^0.58.3",
"style-loader": "^0.21.0",
"styled-components": "^5.1.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"terser-webpack-plugin": "^4.2.3",
"url-loader": "^1.0.1",
"uuid": "^8.1.0",
"val-loader": "^2.1.0",
"webpack": "^4.43.0",
"webpack": "4.44.2",
"webpack-bundle-analyzer": "^3.8.0",
"webpack-dev-middleware": "^3.7.2",
"webpack-hot-middleware": "^2.25.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.4",
"@trbl/eslint-config": "^1.2.4",
"babel-eslint": "^10.0.1",
"cross-env": "^7.0.2",
"eslint": "^6.8.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-jest": "^23.16.0",
"eslint-plugin-jest-dom": "^3.0.1",
"eslint-plugin-jsx-a11y": "^6.2.1",
"eslint-plugin-react": "^7.18.0",
"eslint-plugin-react-hooks": "^2.3.0",
"faker": "^4.1.0",
"form-data": "^3.0.0",
"graphql-request": "^2.0.0",
"nodemon": "^1.19.4"
}
"mongodb": "^3.6.2",
"nodemon": "^1.19.4",
"webpack-cli": "^4.1.0"
},
"files": [
"*.js",
"!jest.config.js",
"payload.d.ts",
"src",
"docs",
"components",
"scss"
]
}

1
scss/vars.scss Normal file
View File

@@ -0,0 +1 @@
@import '../src/admin/scss/vars';

View File

@@ -1,3 +1,4 @@
/* eslint-disable import/prefer-default-export */
import qs from 'qs';
export const requests = {

View File

@@ -0,0 +1,15 @@
<svg width="260" height="260" viewBox="0 0 260 260" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
path {
fill: #333333;
}
@media (prefers-color-scheme: dark) {
path {
fill: white;
}
}
</style>
<path d="M120.59 8.5824L231.788 75.6142V202.829L148.039 251.418V124.203L36.7866 57.2249L120.59 8.5824Z" />
<path d="M112.123 244.353V145.073L28.2114 193.769L112.123 244.353Z" />
</svg>

After

Width:  |  Height:  |  Size: 437 B

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,232 @@
import React, { Suspense, lazy, useState, useEffect } from 'react';
import {
Route, Switch, withRouter, Redirect, useHistory,
} from 'react-router-dom';
import { useConfig } from './providers/Config';
import List from './views/collections/List';
import { useAuth } from './providers/Authentication';
import DefaultTemplate from './templates/Default';
import { requests } from '../api';
import Loading from './elements/Loading';
const Dashboard = lazy(() => import('./views/Dashboard'));
const ForgotPassword = lazy(() => import('./views/ForgotPassword'));
const Login = lazy(() => import('./views/Login'));
const Logout = lazy(() => import('./views/Logout'));
const NotFound = lazy(() => import('./views/NotFound'));
const Verify = lazy(() => import('./views/Verify'));
const CreateFirstUser = lazy(() => import('./views/CreateFirstUser'));
const Edit = lazy(() => import('./views/collections/Edit'));
const EditGlobal = lazy(() => import('./views/Global'));
const ResetPassword = lazy(() => import('./views/ResetPassword'));
const Unauthorized = lazy(() => import('./views/Unauthorized'));
const Account = lazy(() => import('./views/Account'));
const Routes = () => {
const history = useHistory();
const [initialized, setInitialized] = useState(null);
const { user, permissions, permissions: { canAccessAdmin } } = useAuth();
const {
admin: { user: userSlug }, routes, collections, globals,
} = useConfig();
useEffect(() => {
requests.get(`${routes.api}/${userSlug}/init`).then((res) => res.json().then((data) => {
if (data && 'initialized' in data) {
setInitialized(data.initialized);
}
}));
}, [routes, userSlug]);
useEffect(() => {
history.replace();
}, [history]);
return (
<Suspense fallback={<Loading />}>
<Route
path={routes.admin}
render={({ match }) => {
if (initialized === false) {
return (
<Switch>
<Route path={`${match.url}/create-first-user`}>
<CreateFirstUser setInitialized={setInitialized} />
</Route>
<Route>
<Redirect to={`${match.url}/create-first-user`} />
</Route>
</Switch>
);
}
if (initialized === true) {
return (
<Switch>
<Route path={`${match.url}/login`}>
<Login />
</Route>
<Route path={`${match.url}/logout`}>
<Logout />
</Route>
<Route path={`${match.url}/logout-inactivity`}>
<Logout inactivity />
</Route>
<Route path={`${match.url}/forgot`}>
<ForgotPassword />
</Route>
<Route path={`${match.url}/reset/:token`}>
<ResetPassword />
</Route>
{collections.map((collection) => {
if (collection?.auth?.verify) {
return (
<Route
key={`${collection.slug}-verify`}
path={`${match.url}/${collection.slug}/verify/:token`}
exact
>
<Verify collection={collection} />
</Route>
);
}
return null;
})}
<Route
render={() => {
if (user) {
if (canAccessAdmin) {
return (
<DefaultTemplate>
<Switch>
<Route
path={`${match.url}/`}
exact
>
<Dashboard />
</Route>
<Route path={`${match.url}/account`}>
<Account />
</Route>
{collections.map((collection) => (
<Route
key={`${collection.slug}-list`}
path={`${match.url}/collections/${collection.slug}`}
exact
render={(routeProps) => {
if (permissions?.[collection.slug]?.read?.permission) {
return (
<List
{...routeProps}
collection={collection}
/>
);
}
return <Unauthorized />;
}}
/>
))}
{collections.map((collection) => (
<Route
key={`${collection.slug}-create`}
path={`${match.url}/collections/${collection.slug}/create`}
exact
render={(routeProps) => {
if (permissions?.[collection.slug]?.create?.permission) {
return (
<Edit
{...routeProps}
collection={collection}
/>
);
}
return <Unauthorized />;
}}
/>
))}
{collections.map((collection) => (
<Route
key={`${collection.slug}-edit`}
path={`${match.url}/collections/${collection.slug}/:id`}
exact
render={(routeProps) => {
if (permissions?.[collection.slug]?.read?.permission) {
return (
<Edit
isEditing
{...routeProps}
collection={collection}
/>
);
}
return <Unauthorized />;
}}
/>
))}
{globals && globals.map((global) => (
<Route
key={`${global.slug}`}
path={`${match.url}/globals/${global.slug}`}
exact
render={(routeProps) => {
if (permissions?.[global.slug]?.read?.permission) {
return (
<EditGlobal
{...routeProps}
global={global}
/>
);
}
return <Unauthorized />;
}}
/>
))}
<Route path={`${match.url}*`}>
<NotFound />
</Route>
</Switch>
</DefaultTemplate>
);
}
if (canAccessAdmin === false) {
return <Unauthorized />;
}
return <Loading />;
}
if (user === undefined) {
return <Loading />;
}
return <Redirect to={`${match.url}/login`} />;
}}
/>
<Route path={`${match.url}*`}>
<NotFound />
</Route>
</Switch>
);
}
return null;
}}
/>
</Suspense>
);
};
export default withRouter(Routes);

View File

@@ -0,0 +1,69 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import './index.scss';
const baseClass = 'banner';
const Banner = ({
children, className, to, icon, alignIcon, onClick, type,
}) => {
const classes = [
baseClass,
`${baseClass}--type-${type}`,
className && className,
to && `${baseClass}--has-link`,
(to || onClick) && `${baseClass}--has-action`,
icon && `${baseClass}--has-icon`,
icon && `${baseClass}--align-icon-${alignIcon}`,
].filter(Boolean).join(' ');
let RenderedType = 'div';
if (onClick && !to) RenderedType = 'button';
if (to) RenderedType = Link;
return (
<RenderedType
className={classes}
onClick={onClick}
type={RenderedType === 'button' ? 'button' : undefined}
to={to || undefined}
>
{(icon && alignIcon === 'left') && (
<React.Fragment>
{icon}
</React.Fragment>
)}
{children}
{(icon && alignIcon === 'right') && (
<React.Fragment>
{icon}
</React.Fragment>
)}
</RenderedType>
);
};
Banner.defaultProps = {
children: undefined,
className: '',
to: undefined,
icon: undefined,
alignIcon: 'right',
onClick: undefined,
type: 'default',
};
Banner.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
icon: PropTypes.node,
alignIcon: PropTypes.oneOf(['left', 'right']),
onClick: PropTypes.func,
to: PropTypes.string,
type: PropTypes.oneOf(['error', 'success', 'info', 'default']),
};
export default Banner;

View File

@@ -0,0 +1,74 @@
@import '../../../scss/styles.scss';
.banner {
font-size: 1rem;
line-height: base(1);
border: 0;
vertical-align: middle;
background: rgba($color-dark-gray, .1);
color: $color-dark-gray;
border-radius: $style-radius-s;
padding: base(.5);
margin-bottom: $baseline;
&--has-action {
cursor: pointer;
text-decoration: none;
}
&--has-icon {
svg {
display: block;
}
}
&--align-icon-left {
padding-left: base(.125);
}
&--align-icon-right {
padding-right: base(.125);
}
&--type-default {
&.button--has-action {
&:hover {
background: darken($color-dark-gray, .15);
}
&:active {
background: darken($color-dark-gray, .2);
}
}
}
&--type-error {
background: rgba($color-red, .1);
color: $color-red;
&.button--has-action {
&:hover {
background: rgba($color-red, .15);
}
&:active {
background: rgba($color-red, .2);
}
}
}
&--type-success {
background: rgba($color-green, .1);
color: darken($color-green, 20%);
&.button--has-action {
&:hover {
background: rgba($color-green, .15);
}
&:active {
background: rgba($color-green, .2);
}
}
}
}

View File

@@ -79,7 +79,7 @@ const Button = (props) => {
function handleClick(event) {
if (type !== 'submit' && onClick) event.preventDefault();
if (onClick) onClick();
if (onClick) onClick(event);
}
const buttonProps = {

View File

@@ -52,29 +52,55 @@
background-color: $color-dark-gray;
color: white;
&:hover, &:focus {
&:hover {
background: lighten($color-dark-gray, 5%);
}
&:focus {
box-shadow: $focus-box-shadow;
outline: none;
}
&:active {
background: lighten($color-dark-gray, 10%);
}
}
&--style-secondary {
box-shadow: inset 0 0 0 $style-stroke-width $color-dark-gray;
$base-box-shadow: inset 0 0 0 $style-stroke-width $color-dark-gray;
$hover-box-shadow: inset 0 0 0 $style-stroke-width lighten($color-dark-gray, 5%);
box-shadow: $base-box-shadow;
color: $color-dark-gray;
background: none;
&:hover {
background: rgba($color-dark-gray, .02);
box-shadow: inset 0 0 0 $style-stroke-width lighten($color-dark-gray, 5%);
box-shadow: $hover-box-shadow;
}
&:focus {
outline: none;
box-shadow: $hover-box-shadow, $focus-box-shadow;
}
&:active {
background: lighten($color-light-gray, 7%);
}
}
&--style-none {
padding: 0;
margin: 0;
border-radius: 0;
&:focus {
opacity: .8;
}
&:active {
opacity: .7;
}
}
&--round {
@@ -138,6 +164,8 @@
@include color-svg($color-dark-gray);
background: $color-light-gray;
}
outline: none;
}
&:active {
@@ -146,9 +174,4 @@
background: lighten($color-dark-gray, 10%);
}
}
&:focus,
&:active {
outline: none;
}
}

View File

@@ -1,26 +1,37 @@
const getInitialColumnState = (fields, useAsTitle, defaultColumns) => {
let initialColumns = [];
const hasThumbnail = fields.find((field) => field.type === 'thumbnail');
if (Array.isArray(defaultColumns) && defaultColumns.length >= 1) {
return {
columns: defaultColumns,
};
}
if (hasThumbnail) {
initialColumns.push('thumbnail');
}
if (useAsTitle) {
initialColumns.push(useAsTitle);
}
const remainingColumns = fields.filter((field) => field.name !== useAsTitle && field.type !== 'thumbnail')
.slice(0, 3 - initialColumns.length).map((field) => field.name);
const remainingColumns = fields.reduce((remaining, field) => {
if (field.name === useAsTitle) {
return remaining;
}
if (!field.name && Array.isArray(field.fields)) {
return [
...remaining,
...field.fields.map((subField) => subField.name),
];
}
return [
...remaining,
field.name,
];
}, []);
initialColumns = initialColumns.concat(remainingColumns);
initialColumns = initialColumns.slice(0, 4);
return {
columns: initialColumns,

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