Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b932168ce | ||
|
|
681bba82a9 | ||
|
|
5aede8affb | ||
|
|
09dfb9793a | ||
|
|
09897de77d | ||
|
|
0362290d40 | ||
|
|
57ef9fe623 | ||
|
|
38f08d54e3 | ||
|
|
84191ec8fd | ||
|
|
e88be6b251 | ||
|
|
3bec424d05 | ||
|
|
fc56a42fb0 | ||
|
|
05a5cc16bd | ||
|
|
c99b2f35f4 | ||
|
|
8ae7457a3f | ||
|
|
bb8a04dd7b | ||
|
|
a681f5f725 | ||
|
|
613552de0a | ||
|
|
cd38d37242 | ||
|
|
6b6b503ef0 | ||
|
|
f880072697 | ||
|
|
ffc3f10177 | ||
|
|
f9b7e3239e | ||
|
|
09cc61c96a | ||
|
|
a6325c69f4 | ||
|
|
2f1b1a02b1 | ||
|
|
727c5a4a53 | ||
|
|
918d3bd2bc | ||
|
|
2d7bacad09 | ||
|
|
234ed07ad6 | ||
|
|
964fdf779a | ||
|
|
40afb5e8fa | ||
|
|
72c0145816 | ||
|
|
12eb33b5c9 | ||
|
|
ddb238c7e4 | ||
|
|
32980fcafc | ||
|
|
db6315a621 | ||
|
|
6bf0c2aab6 | ||
|
|
3dc9ddcb52 | ||
|
|
352dfa9a09 | ||
|
|
60a3e680dd | ||
|
|
18f98e24e5 | ||
|
|
c599522e44 | ||
|
|
64fef7d380 | ||
|
|
6381d4cf6b | ||
|
|
91016ec206 | ||
|
|
9aeab9548d | ||
|
|
69d7f21b56 | ||
|
|
9de596605b | ||
|
|
650edcf56a | ||
|
|
2c4dedff2c | ||
|
|
870e39961c | ||
|
|
319148ca68 | ||
|
|
6dac68606b | ||
|
|
9716d008a9 | ||
|
|
b5fd68c3dc | ||
|
|
eea9d14749 | ||
|
|
77de6e4b60 | ||
|
|
58f68e3bda | ||
|
|
1ea3763185 | ||
|
|
920251f296 | ||
|
|
dffb554ebe | ||
|
|
7255f6108f | ||
|
|
078392f2c5 | ||
|
|
c2e9407f50 | ||
|
|
a5a4f1490e | ||
|
|
e20555f9cf | ||
|
|
791a222d28 | ||
|
|
cb97090d88 | ||
|
|
923cdc7b6a | ||
|
|
19369b4c33 | ||
|
|
4ec230e8a0 | ||
|
|
7aafe49662 | ||
|
|
33d8ec8a13 | ||
|
|
fb73e772af | ||
|
|
c2692e9b4a | ||
|
|
a0d6fe5ca7 | ||
|
|
7f65e68e82 | ||
|
|
d9f78fc5bf | ||
|
|
b2a5279bcb |
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
@@ -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
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -215,7 +215,6 @@ $RECYCLE.BIN/
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
|
||||
# End of https://www.gitignore.io/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
|
||||
# Ignore all uploads
|
||||
@@ -225,3 +224,7 @@ demo/files
|
||||
|
||||
# Ignore build folder
|
||||
build
|
||||
|
||||
# Ignore built components
|
||||
components/index.js
|
||||
components/styles.css
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as Popup } from '../src/client/components/elements/Popup';
|
||||
|
||||
export { default as MinimalTemplate } from '../src/client/components/templates/Minimal';
|
||||
@@ -1 +0,0 @@
|
||||
export { default as Button } from '../src/client/components/elements/Button';
|
||||
@@ -1,7 +0,0 @@
|
||||
export { default as Form } from '../src/client/components/forms/Form';
|
||||
export { default as Text } from '../src/client/components/forms/field-types/Text';
|
||||
export { default as Group } from '../src/client/components/forms/field-types/Group';
|
||||
export { default as Select } from '../src/client/components/forms/field-types/Select';
|
||||
export { default as Checkbox } from '../src/client/components/forms/field-types/Checkbox';
|
||||
export { default as Submit } from '../src/client/components/forms/Submit';
|
||||
export { default as reduceFieldsToValues } from '../src/client/components/forms/Form/reduceFieldsToValues';
|
||||
@@ -1 +0,0 @@
|
||||
export { default as X } from '../src/client/components/icons/X';
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as LeafButton } from '../src/client/components/forms/field-types/RichText/leaves/Button';
|
||||
export { default as ElementButton } from '../src/client/components/forms/field-types/RichText/elements/Button';
|
||||
export { default as toggleElement } from '../src/client/components/forms/field-types/RichText/elements/toggle';
|
||||
@@ -1 +0,0 @@
|
||||
@import '../src/client/scss/styles.scss';
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default as Edit } from '../src/client/components/views/collections/Edit/Default';
|
||||
export { default as List } from '../src/client/components/views/collections/List/Default';
|
||||
7
components/forms.js
Normal file
7
components/forms.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export { default as Form } from '../src/admin/components/forms/Form';
|
||||
export { default as Text } from '../src/admin/components/forms/field-types/Text';
|
||||
export { default as Group } from '../src/admin/components/forms/field-types/Group';
|
||||
export { default as Select } from '../src/admin/components/forms/field-types/Select';
|
||||
export { default as Checkbox } from '../src/admin/components/forms/field-types/Checkbox';
|
||||
export { default as Submit } from '../src/admin/components/forms/Submit';
|
||||
export { default as reduceFieldsToValues } from '../src/admin/components/forms/Form/reduceFieldsToValues';
|
||||
3
components/rich-text.js
Normal file
3
components/rich-text.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as LeafButton } from '../src/admin/components/forms/field-types/RichText/leaves/Button';
|
||||
export { default as ElementButton } from '../src/admin/components/forms/field-types/RichText/elements/Button';
|
||||
export { default as toggleElement } from '../src/admin/components/forms/field-types/RichText/elements/toggle';
|
||||
2
components/views.js
Normal file
2
components/views.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as Edit } from '../src/admin/components/views/collections/Edit/Default';
|
||||
export { default as List } from '../src/admin/components/views/collections/List/Default';
|
||||
@@ -3,11 +3,11 @@ import PropTypes from 'prop-types';
|
||||
import { Modal, useModal } from '@faceless-ui/modal';
|
||||
import { Transforms } from 'slate';
|
||||
import { useSlate } from 'slate-react';
|
||||
import { MinimalTemplate } from '../../../../../../../admin/components';
|
||||
import { ElementButton } from '../../../../../../../admin/rich-text';
|
||||
import { X } from '../../../../../../../admin/icons';
|
||||
import { Button } from '../../../../../../../admin/elements';
|
||||
import { Form, Text, Checkbox, Select, Submit, reduceFieldsToValues } from '../../../../../../../admin/forms';
|
||||
import MinimalTemplate from '../../../../../../../src/admin/components/templates/Minimal';
|
||||
import { ElementButton } from '../../../../../../../components/rich-text';
|
||||
import X from '../../../../../../../src/admin/components/icons/X';
|
||||
import Button from '../../../../../../../src/admin/components/elements/Button';
|
||||
import { Form, Text, Checkbox, Select, Submit, reduceFieldsToValues } from '../../../../../../../components/forms';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '../../../../../../../admin/styles.scss';
|
||||
@import '../../../../../../../scss/vars.scss';
|
||||
|
||||
.button-rich-text-button {
|
||||
.btn {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '../../../../../../../admin/styles.scss';
|
||||
@import '../../../../../../../scss/vars.scss';
|
||||
|
||||
.rich-text-button {
|
||||
margin: $baseline 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { LeafButton } from '../../../../../../../admin/rich-text';
|
||||
import { LeafButton } from '../../../../../../../components/rich-text';
|
||||
|
||||
const Button = () => (
|
||||
<LeafButton format="purple-background">
|
||||
|
||||
@@ -12,6 +12,7 @@ const AllFields = {
|
||||
},
|
||||
admin: {
|
||||
useAsTitle: 'text',
|
||||
disableScrollOnSuccess: true,
|
||||
},
|
||||
preview: (doc, token) => {
|
||||
if (doc && doc.text) {
|
||||
@@ -188,9 +189,12 @@ const AllFields = {
|
||||
{
|
||||
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,
|
||||
|
||||
@@ -16,7 +16,10 @@ module.exports = {
|
||||
{
|
||||
name: 'layout',
|
||||
label: 'Layout Blocks',
|
||||
singularLabel: 'Block',
|
||||
labels: {
|
||||
singular: 'Block',
|
||||
plural: 'Blocks',
|
||||
},
|
||||
type: 'blocks',
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
localized: true,
|
||||
@@ -25,7 +28,10 @@ module.exports = {
|
||||
{
|
||||
name: 'nonLocalizedLayout',
|
||||
label: 'Non Localized Layout',
|
||||
singularLabel: 'Block',
|
||||
labels: {
|
||||
singular: 'Layout',
|
||||
plural: 'Layouts',
|
||||
},
|
||||
type: 'blocks',
|
||||
blocks: [Email, NumberBlock, Quote, CallToAction],
|
||||
required: true,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Group } from '../../../../../../../admin/forms';
|
||||
import { Group } from '../../../../../../../components/forms';
|
||||
|
||||
const CustomGroup = (props) => (
|
||||
<div className="custom-group">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DefaultList from '../../../../../../src/client/components/views/collections/List/Default';
|
||||
import DefaultList from '../../../../../../src/admin/components/views/collections/List/Default';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
|
||||
272
demo/collections/DefaultValueTest.js
Normal file
272
demo/collections/DefaultValueTest.js
Normal 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;
|
||||
283
demo/collections/DefaultValues.js
Normal file
283
demo/collections/DefaultValues.js
Normal 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;
|
||||
@@ -5,6 +5,7 @@ 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');
|
||||
@@ -52,6 +53,7 @@ module.exports = {
|
||||
Conditions,
|
||||
CustomComponents,
|
||||
File,
|
||||
DefaultValues,
|
||||
Blocks,
|
||||
HiddenFields,
|
||||
Hooks,
|
||||
@@ -122,5 +124,10 @@ module.exports = {
|
||||
console.error('global error config handler', err);
|
||||
},
|
||||
},
|
||||
upload: {
|
||||
limits: {
|
||||
fileSize: 10000000, // 10MB
|
||||
},
|
||||
},
|
||||
webpack: (config) => config,
|
||||
};
|
||||
|
||||
4
hooks.js
4
hooks.js
@@ -1,2 +1,2 @@
|
||||
export { default as useFieldType } from './src/client/components/forms/useFieldType';
|
||||
export { useForm } from './src/client/components/forms/Form/context';
|
||||
export { default as useFieldType } from './src/admin/components/forms/useFieldType';
|
||||
export { useForm } from './src/admin/components/forms/Form/context';
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
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',
|
||||
|
||||
10
jest.react.config.js
Normal file
10
jest.react.config.js
Normal 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',
|
||||
},
|
||||
};
|
||||
39
package.json
39
package.json
@@ -1,22 +1,27 @@
|
||||
{
|
||||
"name": "@payloadcms/payload",
|
||||
"version": "0.0.105",
|
||||
"version": "0.0.118",
|
||||
"description": "CMS and Application Framework",
|
||||
"license": "ISC",
|
||||
"author": "Payload CMS LLC",
|
||||
"main": "index.js",
|
||||
"typings": "payload.d.ts",
|
||||
"sideEffects": false,
|
||||
"bin": {
|
||||
"payload": "./src/bin/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build:components": "webpack --config src/webpack/components.config.js",
|
||||
"build": "PAYLOAD_CONFIG_PATH=demo/payload.config.js node src/bin/build",
|
||||
"build:analyze": "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: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.11.6",
|
||||
@@ -62,26 +67,24 @@
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"http-status": "^1.4.2",
|
||||
"ignore-styles": "^5.0.1",
|
||||
"image-size": "^0.7.5",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
@@ -90,10 +93,10 @@
|
||||
"passport-local-mongoose": "^6.0.1",
|
||||
"pino": "^6.4.1",
|
||||
"pino-pretty": "^4.1.0",
|
||||
"postcss-flexbugs-fixes": "^3.3.1",
|
||||
"postcss-loader": "^2.1.6",
|
||||
"postcss-preset-env": "6.0.6",
|
||||
"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",
|
||||
@@ -109,26 +112,28 @@
|
||||
"react-select": "^3.0.8",
|
||||
"react-simple-code-editor": "^0.11.0",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sass": "^1.27.0",
|
||||
"sass-loader": "7.1.0",
|
||||
"sharp": "^0.25.2",
|
||||
"slate": "^0.58.4",
|
||||
"slate-history": "^0.58.3",
|
||||
"slate-hyperscript": "^0.58.3",
|
||||
"slate-react": "^0.58.3",
|
||||
"style-loader": "^0.21.0",
|
||||
"terser-webpack-plugin": "^4.2.3",
|
||||
"url-loader": "^1.0.1",
|
||||
"uuid": "^8.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",
|
||||
@@ -138,13 +143,15 @@
|
||||
"faker": "^4.1.0",
|
||||
"form-data": "^3.0.0",
|
||||
"graphql-request": "^2.0.0",
|
||||
"nodemon": "^1.19.4"
|
||||
"nodemon": "^1.19.4",
|
||||
"webpack-cli": "^4.0.0"
|
||||
},
|
||||
"files": [
|
||||
"*.js",
|
||||
"!jest.config.js",
|
||||
"payload.d.ts",
|
||||
"src",
|
||||
"admin"
|
||||
"components",
|
||||
"scss"
|
||||
]
|
||||
}
|
||||
|
||||
8
payload.d.ts
vendored
8
payload.d.ts
vendored
@@ -110,6 +110,12 @@ declare module "@payloadcms/payload/types" {
|
||||
type: 'number' | 'text' | 'email' | 'textarea' | 'richText' | 'code' | 'radio' | 'checkbox' | 'date' | 'upload' | 'relationship' | 'row' | 'array' | 'group' | 'select' | 'blocks';
|
||||
localized?: boolean;
|
||||
fields?: PayloadField[];
|
||||
admin?:
|
||||
{
|
||||
position?: string;
|
||||
width?: string;
|
||||
style?: Object;
|
||||
}
|
||||
}
|
||||
|
||||
export type PayloadCollectionHook = (...args: any[]) => any | void;
|
||||
@@ -122,6 +128,8 @@ declare module "@payloadcms/payload/types" {
|
||||
},
|
||||
admin?: {
|
||||
useAsTitle?: string;
|
||||
defaultColumns?: string[];
|
||||
disableScrollOnSuccess?: boolean;
|
||||
components?: any;
|
||||
},
|
||||
hooks?: {
|
||||
|
||||
1
scss/vars.scss
Normal file
1
scss/vars.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import '../src/admin/scss/vars';
|
||||
|
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 437 B |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
69
src/admin/components/elements/Banner/index.js
Normal file
69
src/admin/components/elements/Banner/index.js
Normal 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;
|
||||
74
src/admin/components/elements/Banner/index.scss
Normal file
74
src/admin/components/elements/Banner/index.scss
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import AnimateHeight from 'react-animate-height';
|
||||
import SearchFilter from '../SearchFilter';
|
||||
import ColumnSelector from '../ColumnSelector';
|
||||
import WhereBuilder from '../WhereBuilder';
|
||||
import SortComplex from '../SortComplex';
|
||||
import Button from '../Button';
|
||||
|
||||
import './index.scss';
|
||||
@@ -15,6 +16,8 @@ const ListControls = (props) => {
|
||||
handleChange,
|
||||
collection,
|
||||
enableColumns,
|
||||
enableSort,
|
||||
setSort,
|
||||
collection: {
|
||||
fields,
|
||||
admin: {
|
||||
@@ -96,6 +99,17 @@ const ListControls = (props) => {
|
||||
>
|
||||
Filters
|
||||
</Button>
|
||||
{enableSort && (
|
||||
<Button
|
||||
className={`${baseClass}__toggle-sort`}
|
||||
buttonStyle={visibleDrawer === 'sort' ? undefined : 'secondary'}
|
||||
onClick={() => setVisibleDrawer(visibleDrawer !== 'sort' ? 'sort' : false)}
|
||||
icon="chevron"
|
||||
iconStyle="none"
|
||||
>
|
||||
Sort
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -120,16 +134,31 @@ const ListControls = (props) => {
|
||||
collection={collection}
|
||||
/>
|
||||
</AnimateHeight>
|
||||
{enableSort && (
|
||||
<AnimateHeight
|
||||
className={`${baseClass}__sort`}
|
||||
height={visibleDrawer === 'sort' ? 'auto' : 0}
|
||||
>
|
||||
<SortComplex
|
||||
handleChange={setSort}
|
||||
collection={collection}
|
||||
enableSort
|
||||
/>
|
||||
</AnimateHeight>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ListControls.defaultProps = {
|
||||
enableColumns: true,
|
||||
enableSort: false,
|
||||
};
|
||||
|
||||
ListControls.propTypes = {
|
||||
enableColumns: PropTypes.bool,
|
||||
enableSort: PropTypes.bool,
|
||||
setSort: PropTypes.func.isRequired,
|
||||
collection: PropTypes.shape({
|
||||
admin: PropTypes.shape({
|
||||
useAsTitle: PropTypes.string,
|
||||
@@ -27,7 +27,8 @@
|
||||
}
|
||||
|
||||
&__toggle-columns,
|
||||
&__toggle-where {
|
||||
&__toggle-where,
|
||||
&__toggle-sort {
|
||||
margin: 0 base(.5);
|
||||
min-width: 140px;
|
||||
|
||||
@@ -39,7 +40,8 @@
|
||||
}
|
||||
|
||||
.column-selector,
|
||||
.where-builder {
|
||||
.where-builder,
|
||||
.sort-complex {
|
||||
margin-top: base(1);
|
||||
}
|
||||
|
||||
@@ -68,7 +70,8 @@
|
||||
}
|
||||
|
||||
&__toggle-columns,
|
||||
&__toggle-where {
|
||||
&__toggle-where,
|
||||
&__toggle-sort {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@import '../../../scss//styles';
|
||||
@import '../../../scss/styles';
|
||||
|
||||
div.react-select {
|
||||
div.rs__control {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user