init of the sanitize config rework and custom component config setup
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
import React, { useState, useEffect, Fragment } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
Route, Switch, withRouter, Redirect,
|
Route, Switch, withRouter, Redirect,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import customComponents from 'payload-custom-components';
|
import getSanitizedClientConfig from '../config/getSanitizedClientConfig';
|
||||||
import getSanitizedConfig from '../config/getSanitizedConfig';
|
|
||||||
import { useUser } from './data/User';
|
import { useUser } from './data/User';
|
||||||
import Dashboard from './views/Dashboard';
|
import Dashboard from './views/Dashboard';
|
||||||
import Login from './views/Login';
|
import Login from './views/Login';
|
||||||
@@ -16,11 +15,11 @@ import List from './views/collections/List';
|
|||||||
import EditGlobal from './views/globals/Edit';
|
import EditGlobal from './views/globals/Edit';
|
||||||
import { requests } from '../api';
|
import { requests } from '../api';
|
||||||
|
|
||||||
const config = getSanitizedConfig();
|
const config = getSanitizedClientConfig();
|
||||||
|
|
||||||
const RenderCollectionRoutes = ({ match }) => {
|
const CollectionRoutes = ({ match }) => {
|
||||||
const collectionRoutes = config?.collections.reduce((routesToRender, collection) => {
|
const collectionRoutes = config?.collections.reduce((routesToRender, collection) => {
|
||||||
const ListComponent = customComponents?.collections?.[collection.slug]?.views?.List || List;
|
const ListComponent = List;
|
||||||
routesToRender.push({
|
routesToRender.push({
|
||||||
path: `${match.url}/collections/${collection.slug}`,
|
path: `${match.url}/collections/${collection.slug}`,
|
||||||
component: ListComponent,
|
component: ListComponent,
|
||||||
@@ -127,7 +126,7 @@ const Routes = () => {
|
|||||||
<Dashboard />
|
<Dashboard />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<RenderCollectionRoutes match={match} />
|
<CollectionRoutes match={match} />
|
||||||
|
|
||||||
{config.globals && config.globals.map((global) => {
|
{config.globals && config.globals.map((global) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Cookies from 'universal-cookie';
|
|||||||
import some from 'async-some';
|
import some from 'async-some';
|
||||||
import ReactSelect from '../../../modules/ReactSelect';
|
import ReactSelect from '../../../modules/ReactSelect';
|
||||||
import useFieldType from '../../useFieldType';
|
import useFieldType from '../../useFieldType';
|
||||||
import getSanitizedConfig from '../../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../../config/getSanitizedClientConfig';
|
||||||
import Label from '../../Label';
|
import Label from '../../Label';
|
||||||
import Error from '../../Error';
|
import Error from '../../Error';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ import './index.scss';
|
|||||||
|
|
||||||
const cookies = new Cookies();
|
const cookies = new Cookies();
|
||||||
|
|
||||||
const { serverURL, collections } = getSanitizedConfig();
|
const { serverURL, collections } = getSanitizedClientConfig();
|
||||||
|
|
||||||
const defaultError = 'Please make a selection.';
|
const defaultError = 'Please make a selection.';
|
||||||
const defaultValidate = value => value.length > 0;
|
const defaultValidate = value => value.length > 0;
|
||||||
@@ -49,8 +49,8 @@ class Relationship extends Component {
|
|||||||
some(relationsToSearch, async (relation, callback) => {
|
some(relationsToSearch, async (relation, callback) => {
|
||||||
const response = await fetch(`${serverURL}/${relation}?limit=${maxResultsPerRequest}&page=${lastLoadedPage}`, {
|
const response = await fetch(`${serverURL}/${relation}?limit=${maxResultsPerRequest}&page=${lastLoadedPage}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`
|
Authorization: `Bearer ${token}`,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -59,7 +59,7 @@ class Relationship extends Component {
|
|||||||
return callback(false, {
|
return callback(false, {
|
||||||
data,
|
data,
|
||||||
relation,
|
relation,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
callback({ relation, data });
|
callback({ relation, data });
|
||||||
@@ -73,10 +73,9 @@ class Relationship extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
lastFullyLoadedRelation: relations.indexOf(relation),
|
lastFullyLoadedRelation: relations.indexOf(relation),
|
||||||
lastLoadedPage: 1,
|
lastLoadedPage: 1,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,10 +130,10 @@ class Relationship extends Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
options: [
|
options: [
|
||||||
...options,
|
...options,
|
||||||
...data.docs.map((doc) => ({
|
...data.docs.map(doc => ({
|
||||||
label: doc[collection.useAsTitle],
|
label: doc[collection.useAsTitle],
|
||||||
value: doc.id,
|
value: doc.id,
|
||||||
}))
|
})),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -147,9 +146,9 @@ class Relationship extends Component {
|
|||||||
value: {
|
value: {
|
||||||
relationTo: collection.slug,
|
relationTo: collection.slug,
|
||||||
value: doc.id,
|
value: doc.id,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
|
||||||
if (optionsToAddTo) {
|
if (optionsToAddTo) {
|
||||||
optionsToAddTo.options = [
|
optionsToAddTo.options = [
|
||||||
@@ -167,7 +166,7 @@ class Relationship extends Component {
|
|||||||
options: [
|
options: [
|
||||||
...allOptionGroups,
|
...allOptionGroups,
|
||||||
],
|
],
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -177,8 +176,8 @@ class Relationship extends Component {
|
|||||||
|
|
||||||
handleInputChange = (search) => {
|
handleInputChange = (search) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
search
|
search,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMenuScrollToBottom = () => {
|
handleMenuScrollToBottom = () => {
|
||||||
@@ -213,9 +212,9 @@ class Relationship extends Component {
|
|||||||
|
|
||||||
const valueToRender = this.findValueInOptions(options, value);
|
const valueToRender = this.findValueInOptions(options, value);
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
// ///////////////////////////////////////////
|
||||||
// TODO: simplify formatValue pattern seen below with react select
|
// TODO: simplify formatValue pattern seen below with react select
|
||||||
/////////////////////////////////////////////
|
// ///////////////////////////////////////////
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -306,23 +305,23 @@ const RelationshipFieldType = (props) => {
|
|||||||
if (hasMultipleRelations) {
|
if (hasMultipleRelations) {
|
||||||
return {
|
return {
|
||||||
...valueToFormat,
|
...valueToFormat,
|
||||||
value: valueToFormat.value.id
|
value: valueToFormat.value.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return valueToFormat.id;
|
return valueToFormat.id;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (defaultValue) {
|
if (defaultValue) {
|
||||||
if (hasMany && Array.isArray(defaultValue)) {
|
if (hasMany && Array.isArray(defaultValue)) {
|
||||||
let formattedDefaultValue = [];
|
const formattedDefaultValue = [];
|
||||||
defaultValue.forEach((individualValue) => {
|
defaultValue.forEach((individualValue) => {
|
||||||
formattedDefaultValue.push(formatDefaultValue(individualValue));
|
formattedDefaultValue.push(formatDefaultValue(individualValue));
|
||||||
})
|
});
|
||||||
setFormattedDefaultValue(formattedDefaultValue);
|
setFormattedDefaultValue(formattedDefaultValue);
|
||||||
} else {
|
} else {
|
||||||
setFormattedDefaultValue(formatDefaultValue(defaultValue));
|
setFormattedDefaultValue(formatDefaultValue(defaultValue));
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}, [defaultValue]);
|
}, [defaultValue]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Sidebar from '../Sidebar';
|
import Sidebar from 'payload/Sidebar';
|
||||||
import StepNav, { useStepNav, StepNavProvider } from '../../modules/StepNav';
|
import StepNav, { useStepNav, StepNavProvider } from '../../modules/StepNav';
|
||||||
import { StatusListProvider } from '../../modules/Status';
|
import { StatusListProvider } from '../../modules/Status';
|
||||||
import Localizer from '../../modules/Localizer';
|
import Localizer from '../../modules/Localizer';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useLocation, NavLink, Link } from 'react-router-dom';
|
import { useLocation, NavLink, Link } from 'react-router-dom';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
|
|
||||||
import Arrow from '../../graphics/Arrow';
|
import Arrow from '../../graphics/Arrow';
|
||||||
import Icon from '../../graphics/Icon';
|
import Icon from '../../graphics/Icon';
|
||||||
@@ -13,7 +13,7 @@ const {
|
|||||||
routes: {
|
routes: {
|
||||||
admin,
|
admin,
|
||||||
},
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const Sidebar = () => {
|
const Sidebar = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React, { Component } from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import Filter from '../Filter';
|
import Filter from '../Filter';
|
||||||
import Table from '../../layout/Table';
|
import Table from '../../layout/Table';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
|
|
||||||
const { routes: { admin } } = getSanitizedConfig();
|
const { routes: { admin } } = getSanitizedClientConfig();
|
||||||
|
|
||||||
class SearchableTable extends Component {
|
class SearchableTable extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|||||||
@@ -2,115 +2,127 @@ import React, { Component } from 'react';
|
|||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import Button from '../../controls/Button';
|
import Button from '../../controls/Button';
|
||||||
import api from '../../../api';
|
import api from '../../../api';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
const config = getSanitizedConfig();
|
const config = getSanitizedClientConfig();
|
||||||
|
|
||||||
class UploadMedia extends Component {
|
class UploadMedia extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
dragging: false,
|
dragging: false,
|
||||||
selectingFile: false,
|
selectingFile: false,
|
||||||
files: null
|
files: null,
|
||||||
}
|
};
|
||||||
|
|
||||||
this.dropRef = React.createRef();
|
this.dropRef = React.createRef();
|
||||||
this.dragCounter = 0;
|
this.dragCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
let div = this.dropRef.current
|
const div = this.dropRef.current;
|
||||||
div.addEventListener('dragenter', this.handleDragIn)
|
div.addEventListener('dragenter', this.handleDragIn);
|
||||||
div.addEventListener('dragleave', this.handleDragOut)
|
div.addEventListener('dragleave', this.handleDragOut);
|
||||||
div.addEventListener('dragover', this.handleDrag)
|
div.addEventListener('dragover', this.handleDrag);
|
||||||
div.addEventListener('drop', this.handleDrop)
|
div.addEventListener('drop', this.handleDrop);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
let div = this.dropRef.current
|
const div = this.dropRef.current;
|
||||||
div.removeEventListener('dragenter', this.handleDragIn)
|
div.removeEventListener('dragenter', this.handleDragIn);
|
||||||
div.removeEventListener('dragleave', this.handleDragOut)
|
div.removeEventListener('dragleave', this.handleDragOut);
|
||||||
div.removeEventListener('dragover', this.handleDrag)
|
div.removeEventListener('dragover', this.handleDrag);
|
||||||
div.removeEventListener('drop', this.handleDrop)
|
div.removeEventListener('drop', this.handleDrop);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDrag = e => {
|
handleDrag = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDragIn = e => {
|
handleDragIn = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.dragCounter++;
|
this.dragCounter++;
|
||||||
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
|
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
|
||||||
this.setState({ dragging: true })
|
this.setState({ dragging: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDragOut = e => {
|
handleDragOut = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.dragCounter--;
|
this.dragCounter--;
|
||||||
if (this.dragCounter > 0) return;
|
if (this.dragCounter > 0) return;
|
||||||
this.setState({ dragging: false })
|
this.setState({ dragging: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDrop = e => {
|
handleDrop = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.setState({ dragging: false })
|
this.setState({ dragging: false });
|
||||||
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
||||||
this.setState({
|
this.setState({
|
||||||
files: e.dataTransfer.files,
|
files: e.dataTransfer.files,
|
||||||
dragging: false
|
dragging: false,
|
||||||
})
|
});
|
||||||
|
|
||||||
e.dataTransfer.clearData();
|
e.dataTransfer.clearData();
|
||||||
this.dragCounter = 0;
|
this.dragCounter = 0;
|
||||||
} else {
|
} else {
|
||||||
this.setState({ dragging: false })
|
this.setState({ dragging: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSelectFile = e => {
|
handleSelectFile = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.setState({
|
this.setState({
|
||||||
selectingFile: true
|
selectingFile: true,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectingFile = selectingFile => {
|
setSelectingFile = (selectingFile) => {
|
||||||
this.setState({ selectingFile })
|
this.setState({ selectingFile });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div ref={this.dropRef} className={`upload-media${this.state.dragging ? ' dragging' : ''}`}>
|
<div
|
||||||
|
ref={this.dropRef}
|
||||||
|
className={`upload-media${this.state.dragging ? ' dragging' : ''}`}
|
||||||
|
>
|
||||||
<span className="instructions">Drag and drop a file here</span>
|
<span className="instructions">Drag and drop a file here</span>
|
||||||
<span className="or">—or—</span>
|
<span className="or">—or—</span>
|
||||||
<Button className="select-file" type="secondary" onClick={this.handleSelectFile}>Select a File</Button>
|
<Button
|
||||||
<UploadMediaForm files={this.state.files} selectingFile={this.state.selectingFile} config={config} setSelectingFile={this.setSelectingFile} />
|
className="select-file"
|
||||||
|
type="secondary"
|
||||||
|
onClick={this.handleSelectFile}
|
||||||
|
>
|
||||||
|
Select a File
|
||||||
|
</Button>
|
||||||
|
<UploadMediaForm
|
||||||
|
files={this.state.files}
|
||||||
|
selectingFile={this.state.selectingFile}
|
||||||
|
config={config}
|
||||||
|
setSelectingFile={this.setSelectingFile}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to set up a separate component with a Portal
|
// Need to set up a separate component with a Portal
|
||||||
// to make sure forms are not embedded within other forms
|
// to make sure forms are not embedded within other forms
|
||||||
class UploadMediaForm extends Component {
|
class UploadMediaForm extends Component {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
submitted: false
|
submitted: false,
|
||||||
}
|
};
|
||||||
this.formRef = React.createRef();
|
this.formRef = React.createRef();
|
||||||
this.inputRef = React.createRef();
|
this.inputRef = React.createRef();
|
||||||
}
|
}
|
||||||
@@ -148,18 +160,23 @@ class UploadMediaForm extends Component {
|
|||||||
const data = new FormData(this.formRef.current);
|
const data = new FormData(this.formRef.current);
|
||||||
api.requests.post(`${this.props.config.serverURL}/upload`, data).then(
|
api.requests.post(`${this.props.config.serverURL}/upload`, data).then(
|
||||||
res => console.log(res),
|
res => console.log(res),
|
||||||
err => {
|
(err) => {
|
||||||
console.warn(err);
|
console.warn(err);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return createPortal(
|
return createPortal(
|
||||||
<form ref={this.formRef}>
|
<form ref={this.formRef}>
|
||||||
<input type="file" name="files" ref={this.inputRef} />
|
<input
|
||||||
|
type="file"
|
||||||
|
name="files"
|
||||||
|
ref={this.inputRef}
|
||||||
|
/>
|
||||||
</form>,
|
</form>,
|
||||||
document.getElementById('portal'))
|
document.getElementById('portal'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import ContentBlock from '../../layout/ContentBlock';
|
|||||||
import Form from '../../forms/Form';
|
import Form from '../../forms/Form';
|
||||||
import RenderFields from '../../forms/RenderFields';
|
import RenderFields from '../../forms/RenderFields';
|
||||||
import FormSubmit from '../../forms/Submit';
|
import FormSubmit from '../../forms/Submit';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
import { useUser } from '../../data/User';
|
import { useUser } from '../../data/User';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
@@ -16,7 +16,7 @@ const {
|
|||||||
routes: {
|
routes: {
|
||||||
admin,
|
admin,
|
||||||
},
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const passwordField = {
|
const passwordField = {
|
||||||
name: 'password',
|
name: 'password',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import DefaultTemplate from '../../layout/DefaultTemplate';
|
import DefaultTemplate from '../../layout/DefaultTemplate';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ const {
|
|||||||
routes: {
|
routes: {
|
||||||
admin,
|
admin,
|
||||||
},
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const baseClass = 'dashboard';
|
const baseClass = 'dashboard';
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Form from '../../forms/Form';
|
|||||||
import Email from '../../forms/field-types/Email';
|
import Email from '../../forms/field-types/Email';
|
||||||
import Password from '../../forms/field-types/Password';
|
import Password from '../../forms/field-types/Password';
|
||||||
import FormSubmit from '../../forms/Submit';
|
import FormSubmit from '../../forms/Submit';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
import Button from '../../controls/Button';
|
import Button from '../../controls/Button';
|
||||||
import { useUser } from '../../data/User';
|
import { useUser } from '../../data/User';
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ const {
|
|||||||
routes: {
|
routes: {
|
||||||
admin,
|
admin,
|
||||||
},
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
const { addStatus } = useStatusList();
|
const { addStatus } = useStatusList();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useUser } from '../../data/User';
|
import { useUser } from '../../data/User';
|
||||||
import ContentBlock from '../../layout/ContentBlock';
|
import ContentBlock from '../../layout/ContentBlock';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
import Button from '../../controls/Button';
|
import Button from '../../controls/Button';
|
||||||
|
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
@@ -12,7 +12,7 @@ const {
|
|||||||
routes: {
|
routes: {
|
||||||
admin,
|
admin,
|
||||||
},
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const Logout = () => {
|
const Logout = () => {
|
||||||
const { logOut } = useUser();
|
const { logOut } = useUser();
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import getSanitizedConfig from '../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../config/getSanitizedClientConfig';
|
||||||
import Button from '../../controls/Button';
|
import Button from '../../controls/Button';
|
||||||
import DefaultTemplate from '../../layout/DefaultTemplate';
|
import DefaultTemplate from '../../layout/DefaultTemplate';
|
||||||
|
|
||||||
const { routes: { admin } } = getSanitizedConfig();
|
const { routes: { admin } } = getSanitizedClientConfig();
|
||||||
|
|
||||||
const NotFound = () => {
|
const NotFound = () => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useRouteMatch, useHistory } from 'react-router-dom';
|
import { useRouteMatch, useHistory } from 'react-router-dom';
|
||||||
import getSanitizedConfig from '../../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../../config/getSanitizedClientConfig';
|
||||||
import DefaultTemplate from '../../../layout/DefaultTemplate';
|
import DefaultTemplate from '../../../layout/DefaultTemplate';
|
||||||
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
|
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
|
||||||
import Form from '../../../forms/Form';
|
import Form from '../../../forms/Form';
|
||||||
@@ -16,9 +16,9 @@ import './index.scss';
|
|||||||
const {
|
const {
|
||||||
serverURL,
|
serverURL,
|
||||||
routes: {
|
routes: {
|
||||||
admin
|
admin,
|
||||||
}
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const baseClass = 'collection-edit';
|
const baseClass = 'collection-edit';
|
||||||
|
|
||||||
@@ -33,14 +33,14 @@ const EditView = (props) => {
|
|||||||
status: {
|
status: {
|
||||||
message: json.message,
|
message: json.message,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} : null;
|
} : null;
|
||||||
|
|
||||||
const [{ data }] = usePayloadAPI(
|
const [{ data }] = usePayloadAPI(
|
||||||
(isEditing ? `${serverURL}/${collection.slug}/${id}` : null),
|
(isEditing ? `${serverURL}/${collection.slug}/${id}` : null),
|
||||||
{ initialParams: { 'fallback-locale': 'null' } }
|
{ initialParams: { 'fallback-locale': 'null' } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const nav = [{
|
const nav = [{
|
||||||
@@ -50,12 +50,12 @@ const EditView = (props) => {
|
|||||||
|
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
nav.push({
|
nav.push({
|
||||||
label: data ? data[collection.useAsTitle] : ''
|
label: data ? data[collection.useAsTitle] : '',
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
nav.push({
|
nav.push({
|
||||||
label: 'Create New'
|
label: 'Create New',
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -66,26 +66,45 @@ const EditView = (props) => {
|
|||||||
<header className={`${baseClass}__header`}>
|
<header className={`${baseClass}__header`}>
|
||||||
{isEditing && (
|
{isEditing && (
|
||||||
<h1>
|
<h1>
|
||||||
Edit {Object.keys(data).length > 0 &&
|
Edit
|
||||||
(data[collection.useAsTitle] ? data[collection.useAsTitle] : '[Untitled]')
|
{' '}
|
||||||
|
{Object.keys(data).length > 0
|
||||||
|
&& (data[collection.useAsTitle] ? data[collection.useAsTitle] : '[Untitled]')
|
||||||
}
|
}
|
||||||
</h1>
|
</h1>
|
||||||
)}
|
)}
|
||||||
{!isEditing &&
|
{!isEditing
|
||||||
<h1>Create New {collection.labels.singular}</h1>
|
&& (
|
||||||
|
<h1>
|
||||||
|
Create New
|
||||||
|
{' '}
|
||||||
|
{collection.labels.singular}
|
||||||
|
</h1>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
</header>
|
</header>
|
||||||
<Form className={`${baseClass}__form`} method={id ? 'put' : 'post'} action={`${serverURL}/${collection.slug}${id ? `/${id}` : ''}`} handleAjaxResponse={handleAjaxResponse}>
|
<Form
|
||||||
<StickyHeader showStatus={true}
|
className={`${baseClass}__form`}
|
||||||
|
method={id ? 'put' : 'post'}
|
||||||
|
action={`${serverURL}/${collection.slug}${id ? `/${id}` : ''}`}
|
||||||
|
handleAjaxResponse={handleAjaxResponse}
|
||||||
|
>
|
||||||
|
<StickyHeader
|
||||||
|
showStatus
|
||||||
content={
|
content={
|
||||||
<APIURL url={isEditing && `${serverURL}/${collection.slug}/${data.id}`} />
|
<APIURL url={isEditing && `${serverURL}/${collection.slug}/${data.id}`} />
|
||||||
} action={
|
}
|
||||||
|
action={(
|
||||||
<>
|
<>
|
||||||
<Button type="secondary">Preview</Button>
|
<Button type="secondary">Preview</Button>
|
||||||
<FormSubmit>Save</FormSubmit>
|
<FormSubmit>Save</FormSubmit>
|
||||||
</>
|
</>
|
||||||
} />
|
)}
|
||||||
<RenderFields fields={collection.fields} initialData={data} />
|
/>
|
||||||
|
<RenderFields
|
||||||
|
fields={collection.fields}
|
||||||
|
initialData={data}
|
||||||
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
</DefaultTemplate>
|
</DefaultTemplate>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useLocation } from 'react-router-dom';
|
|||||||
import queryString from 'qs';
|
import queryString from 'qs';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
|
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
|
||||||
import getSanitizedConfig from '../../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../../config/getSanitizedClientConfig';
|
||||||
import DefaultTemplate from '../../../layout/DefaultTemplate';
|
import DefaultTemplate from '../../../layout/DefaultTemplate';
|
||||||
import HeadingButton from '../../../modules/HeadingButton';
|
import HeadingButton from '../../../modules/HeadingButton';
|
||||||
import SearchableTable from '../../../modules/SearchableTable';
|
import SearchableTable from '../../../modules/SearchableTable';
|
||||||
@@ -16,7 +16,7 @@ const {
|
|||||||
routes: {
|
routes: {
|
||||||
admin,
|
admin,
|
||||||
},
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const ListView = (props) => {
|
const ListView = (props) => {
|
||||||
const { collection } = props;
|
const { collection } = props;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import getSanitizedConfig from '../../../../config/getSanitizedConfig';
|
import getSanitizedClientConfig from '../../../../config/getSanitizedClientConfig';
|
||||||
import DefaultTemplate from '../../../layout/DefaultTemplate';
|
import DefaultTemplate from '../../../layout/DefaultTemplate';
|
||||||
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
|
import usePayloadAPI from '../../../../hooks/usePayloadAPI';
|
||||||
import Form from '../../../forms/Form';
|
import Form from '../../../forms/Form';
|
||||||
@@ -15,9 +15,9 @@ import './index.scss';
|
|||||||
const {
|
const {
|
||||||
serverURL,
|
serverURL,
|
||||||
routes: {
|
routes: {
|
||||||
admin
|
admin,
|
||||||
}
|
},
|
||||||
} = getSanitizedConfig();
|
} = getSanitizedClientConfig();
|
||||||
|
|
||||||
const baseClass = 'global-edit';
|
const baseClass = 'global-edit';
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ const EditView = (props) => {
|
|||||||
|
|
||||||
const [{ data }] = usePayloadAPI(
|
const [{ data }] = usePayloadAPI(
|
||||||
`${serverURL}/globals/${global.slug}`,
|
`${serverURL}/globals/${global.slug}`,
|
||||||
{ initialParams: { 'fallback-locale': 'null' } }
|
{ initialParams: { 'fallback-locale': 'null' } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const nav = [{
|
const nav = [{
|
||||||
@@ -41,20 +41,32 @@ const EditView = (props) => {
|
|||||||
>
|
>
|
||||||
<header className={`${baseClass}__header`}>
|
<header className={`${baseClass}__header`}>
|
||||||
<h1>
|
<h1>
|
||||||
Edit {global.label}
|
Edit
|
||||||
|
{' '}
|
||||||
|
{global.label}
|
||||||
</h1>
|
</h1>
|
||||||
</header>
|
</header>
|
||||||
<Form className={`${baseClass}__form`} method={data ? 'put' : 'post'} action={`${serverURL}/globals/${global.slug}`}>
|
<Form
|
||||||
<StickyHeader showStatus={true}
|
className={`${baseClass}__form`}
|
||||||
|
method={data ? 'put' : 'post'}
|
||||||
|
action={`${serverURL}/globals/${global.slug}`}
|
||||||
|
>
|
||||||
|
<StickyHeader
|
||||||
|
showStatus
|
||||||
content={
|
content={
|
||||||
<APIURL url={`${serverURL}/globals/${global.slug}`} />
|
<APIURL url={`${serverURL}/globals/${global.slug}`} />
|
||||||
} action={
|
}
|
||||||
|
action={(
|
||||||
<>
|
<>
|
||||||
<Button type="secondary">Preview</Button>
|
<Button type="secondary">Preview</Button>
|
||||||
<FormSubmit>Save</FormSubmit>
|
<FormSubmit>Save</FormSubmit>
|
||||||
</>
|
</>
|
||||||
} />
|
)}
|
||||||
<RenderFields fields={global.fields} initialData={data} />
|
/>
|
||||||
|
<RenderFields
|
||||||
|
fields={global.fields}
|
||||||
|
initialData={data}
|
||||||
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
</DefaultTemplate>
|
</DefaultTemplate>
|
||||||
);
|
);
|
||||||
|
|||||||
5
src/client/config/getSanitizedClientConfig.js
Normal file
5
src/client/config/getSanitizedClientConfig.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import config from 'payload-config';
|
||||||
|
import sanitizeConfig from '../../utilities/sanitizeConfig';
|
||||||
|
|
||||||
|
const getSanitizedClientConfig = () => sanitizeConfig(config);
|
||||||
|
export default getSanitizedClientConfig;
|
||||||
@@ -104,8 +104,8 @@ module.exports = (config) => {
|
|||||||
modules: ['node_modules', path.resolve(__dirname, '../../../node_modules')],
|
modules: ['node_modules', path.resolve(__dirname, '../../../node_modules')],
|
||||||
alias: {
|
alias: {
|
||||||
'payload-scss-overrides': config.paths.scssOverrides,
|
'payload-scss-overrides': config.paths.scssOverrides,
|
||||||
'payload-custom-components': config.paths.components,
|
|
||||||
'payload-config': config.paths.config,
|
'payload-config': config.paths.config,
|
||||||
|
'payload/Sidebar': (config.customComponents.layout && config.customComponents.layout.Sidebar) ? config.customComponents.layout.Sidebar : path.resolve(__dirname, '../components/layout/Sidebar/index.js'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
21
src/index.js
21
src/index.js
@@ -11,13 +11,13 @@ const baseUserFields = require('./auth/baseFields');
|
|||||||
const baseUploadFields = require('./uploads/baseUploadFields');
|
const baseUploadFields = require('./uploads/baseUploadFields');
|
||||||
const baseImageFields = require('./uploads/baseImageFields');
|
const baseImageFields = require('./uploads/baseImageFields');
|
||||||
const registerUploadRoutes = require('./uploads/routes');
|
const registerUploadRoutes = require('./uploads/routes');
|
||||||
const registerConfigRoute = require('./routes/config');
|
|
||||||
const validateCollection = require('./collections/validate');
|
const validateCollection = require('./collections/validate');
|
||||||
const buildCollectionSchema = require('./collections/buildSchema');
|
const buildCollectionSchema = require('./collections/buildSchema');
|
||||||
const registerCollectionRoutes = require('./collections/registerRoutes');
|
const registerCollectionRoutes = require('./collections/registerRoutes');
|
||||||
const validateGlobals = require('./globals/validate');
|
const validateGlobals = require('./globals/validate');
|
||||||
const registerGlobalSchema = require('./globals/registerSchema');
|
const registerGlobalSchema = require('./globals/registerSchema');
|
||||||
const registerGlobalRoutes = require('./globals/registerRoutes');
|
const registerGlobalRoutes = require('./globals/registerRoutes');
|
||||||
|
const sanitizeConfig = require('./utilities/sanitizeConfig');
|
||||||
|
|
||||||
class Payload {
|
class Payload {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
@@ -28,19 +28,18 @@ class Payload {
|
|||||||
this.getCollections.bind(this);
|
this.getCollections.bind(this);
|
||||||
this.getGlobals.bind(this);
|
this.getGlobals.bind(this);
|
||||||
|
|
||||||
// Setup & initialization
|
|
||||||
connectMongoose(options.config.mongoURL);
|
|
||||||
registerExpressMiddleware(options);
|
|
||||||
initPassport(options.app);
|
|
||||||
initUploads(options);
|
|
||||||
initCORS(options);
|
|
||||||
registerConfigRoute(options, this.getCollections, this.getGlobals);
|
|
||||||
|
|
||||||
// Bind options, app, router
|
// Bind options, app, router
|
||||||
this.config = options.config;
|
|
||||||
this.app = options.app;
|
this.app = options.app;
|
||||||
|
this.config = sanitizeConfig(options.config);
|
||||||
this.router = options.router;
|
this.router = options.router;
|
||||||
|
|
||||||
|
// Setup & initialization
|
||||||
|
connectMongoose(this.config.mongoURL);
|
||||||
|
registerExpressMiddleware(this.app, this.config, this.router);
|
||||||
|
initPassport(this.app);
|
||||||
|
initUploads(this.app, this.config);
|
||||||
|
initCORS(this.app, this.config);
|
||||||
|
|
||||||
// Register and bind required collections
|
// Register and bind required collections
|
||||||
this.registerUser();
|
this.registerUser();
|
||||||
this.registerUpload();
|
this.registerUpload();
|
||||||
@@ -61,7 +60,7 @@ class Payload {
|
|||||||
this.registerGlobals(this.config.globals);
|
this.registerGlobals(this.config.globals);
|
||||||
|
|
||||||
// Enable client webpack
|
// Enable client webpack
|
||||||
if (!this.config.disableAdmin) initWebpack(options);
|
if (!this.config.disableAdmin) initWebpack(this.app, this.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerUser() {
|
registerUser() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const initCORS = ({ config, app }) => {
|
const initCORS = (app, config) => {
|
||||||
if (config.cors) {
|
if (config.cors) {
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
if (config.cors.indexOf(req.headers.origin) > -1) {
|
if (config.cors.indexOf(req.headers.origin) > -1) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const bodyParser = require('body-parser');
|
|||||||
const methodOverride = require('method-override');
|
const methodOverride = require('method-override');
|
||||||
const localizationMiddleware = require('../localization/middleware');
|
const localizationMiddleware = require('../localization/middleware');
|
||||||
|
|
||||||
const registerExpressMiddleware = ({ app, config, router }) => {
|
const registerExpressMiddleware = (app, config, router) => {
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(methodOverride('X-HTTP-Method-Override'));
|
app.use(methodOverride('X-HTTP-Method-Override'));
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
|
||||||
const initUploads = ({ config, app }) => {
|
const initUploads = (app, config) => {
|
||||||
const staticUrl = config.staticUrl ? config.staticUrl : `/${config.staticDir}`;
|
const staticUrl = config.staticUrl ? config.staticUrl : `/${config.staticDir}`;
|
||||||
app.use(staticUrl, express.static(config.staticDir));
|
app.use(staticUrl, express.static(config.staticDir));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const webpackDevMiddleware = require('webpack-dev-middleware');
|
const webpackDevMiddleware = require('webpack-dev-middleware');
|
||||||
const webpackHotMiddleware = require('webpack-hot-middleware');
|
const webpackHotMiddleware = require('webpack-hot-middleware');
|
||||||
const path = require('path');
|
|
||||||
const getWebpackDevConfig = require('../client/config/getWebpackDevConfig');
|
const getWebpackDevConfig = require('../client/config/getWebpackDevConfig');
|
||||||
|
|
||||||
const initWebpack = ({ config, app }) => {
|
const initWebpack = (app, config) => {
|
||||||
const webpackDevConfig = getWebpackDevConfig(config);
|
const webpackDevConfig = getWebpackDevConfig(config);
|
||||||
const compiler = webpack(webpackDevConfig);
|
const compiler = webpack(webpackDevConfig);
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
const passport = require('passport');
|
|
||||||
|
|
||||||
const registerConfigRoute = ({ router, config }, getCollections, getGlobals) => {
|
|
||||||
router.use('/config',
|
|
||||||
passport.authenticate('jwt', { session: false }),
|
|
||||||
(req, res) => {
|
|
||||||
const registeredCollections = getCollections();
|
|
||||||
const globals = getGlobals();
|
|
||||||
|
|
||||||
const collections = {};
|
|
||||||
const contentBlocks = {};
|
|
||||||
Object.keys(registeredCollections).forEach((key) => {
|
|
||||||
const fullConfig = registeredCollections[key].config;
|
|
||||||
|
|
||||||
const collectionConfig = { ...fullConfig };
|
|
||||||
|
|
||||||
delete collectionConfig.plugins;
|
|
||||||
delete collectionConfig.policies;
|
|
||||||
|
|
||||||
if (collectionConfig.useAsContentBlock) {
|
|
||||||
contentBlocks[collectionConfig.slug] = collectionConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
collections[collectionConfig.slug] = collectionConfig;
|
|
||||||
});
|
|
||||||
res.json({
|
|
||||||
...config,
|
|
||||||
collections,
|
|
||||||
globals,
|
|
||||||
contentBlocks,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = registerConfigRoute;
|
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
import config from 'payload-config';
|
const sanitizeConfig = (config) => {
|
||||||
|
|
||||||
const getSanitizedConfig = () => {
|
|
||||||
const sanitizedConfig = { ...config };
|
const sanitizedConfig = { ...config };
|
||||||
|
|
||||||
sanitizedConfig.routes = {
|
sanitizedConfig.routes = {
|
||||||
admin: (config.routes && config.routes.admin) ? config.routes.admin : '/admin',
|
admin: (config.routes && config.routes.admin) ? config.routes.admin : '/admin',
|
||||||
api: (config.routes && config.routes.api) ? config.routes.api : '/api',
|
api: (config.routes && config.routes.api) ? config.routes.api : '/api',
|
||||||
};
|
};
|
||||||
|
sanitizedConfig.customComponents = { ...(config.customComponents || {}) };
|
||||||
|
|
||||||
return sanitizedConfig;
|
return sanitizedConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default getSanitizedConfig;
|
module.exports = sanitizeConfig;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import usePayloadAPI from './src/client/hooks/usePayloadAPI';
|
import usePayloadAPI from './src/client/hooks/usePayloadAPI';
|
||||||
import getSanitizedConfig from './src/client/config/getSanitizedConfig';
|
import getSanitizedClientConfig from './src/client/config/getSanitizedClientConfig';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
usePayloadAPI,
|
usePayloadAPI,
|
||||||
getSanitizedConfig,
|
getSanitizedClientConfig,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user