acklen-keystone
Version:
Web Application Framework and Admin GUI / Content Management System built on Express.js and Mongoose
215 lines (205 loc) • 6.05 kB
JavaScript
/**
* Item View
*
* This is the item view, it is rendered when users visit a page of a specific
* item. This mainly renders the form to edit the item content in.
*/
import React from 'react';
import { Center, Container, Spinner } from '../../elemental';
import { connect } from 'react-redux';
import { Link } from 'react-router';
import { listsByKey } from '../../../utils/lists';
import CreateForm from '../../shared/CreateForm';
import Alert from '../../elemental/Alert';
import EditForm from './components/EditForm';
import EditFormHeader from './components/EditFormHeader';
import RelatedItemsList from './components/RelatedItemsList/RelatedItemsList';
import { checkPermissionForUserByPath } from '../../../utils/permissions';
import {
selectItem,
loadItemData,
} from './actions';
import {
selectList,
} from '../List/actions';
var ItemView = React.createClass({
displayName: 'ItemView',
contextTypes: {
router: React.PropTypes.object.isRequired,
},
getInitialState () {
return {
createIsOpen: false,
isAdministrator: false,
};
},
componentDidMount () {
checkPermissionForUserByPath(this.props.location, 2);
// When we directly navigate to an item without coming from another client
// side routed page before, we need to select the list before initializing the item
// We also need to update when the list id has changed
if (!this.props.currentList || this.props.currentList.id !== this.props.params.listId) {
this.props.dispatch(selectList(this.props.params.listId));
}
this.initializeItem(this.props.params.itemId);
},
componentWillReceiveProps (nextProps) {
// We've opened a new item from the client side routing, so initialize
// again with the new item id
if (nextProps.params.itemId !== this.props.params.itemId) {
this.props.dispatch(selectList(nextProps.params.listId));
this.initializeItem(nextProps.params.itemId);
}
if (nextProps.data) {
this.checkPermissionForAdminUser(nextProps.data);
}
},
// Initialize an item
initializeItem (itemId) {
this.props.dispatch(selectItem(itemId));
this.props.dispatch(loadItemData());
},
// Called when a new item is created
onCreate (item) {
// Hide the create form
this.toggleCreateModal(false);
// Redirect to newly created item path
const list = this.props.currentList;
this.context.router.push(`${Keystone.adminPath}/${list.path}/${item.id}`);
},
// Open and close the create new item modal
toggleCreateModal (visible) {
this.setState({
createIsOpen: visible,
});
},
checkPermissionForAdminUser (user) {
this.setState({
isAdministrator: user.fields.isAdministrator
&& Keystone.user.id === user.id,
});
},
// Render this items relationships
renderRelationships () {
const { relationships } = this.props.currentList;
const keys = Object.keys(relationships);
if (!keys.length) return;
return (
<div className="Relationships">
<Container>
<h2>Relationships</h2>
{keys.map(key => {
const relationship = relationships[key];
const refList = listsByKey[relationship.ref];
const { currentList, params, relationshipData, drag } = this.props;
return (
<RelatedItemsList
key={relationship.path}
list={currentList}
refList={refList}
relatedItemId={params.itemId}
relationship={relationship}
items={relationshipData[relationship.path]}
dragNewSortOrder={drag.newSortOrder}
dispatch={this.props.dispatch}
/>
);
})}
</Container>
</div>
);
},
// Handle errors
handleError (error) {
const detail = error.detail;
if (detail) {
// Item not found
if (detail.name === 'CastError'
&& detail.path === '_id') {
return (
<Container>
<Alert color="danger" style={{ marginTop: '2em' }}>
No item matching id "{this.props.routeParams.itemId}".
<Link to={`${Keystone.adminPath}/${this.props.routeParams.listId}`}>
Got back to {this.props.routeParams.listId}?
</Link>
</Alert>
</Container>
);
}
}
if (error.message) {
// Server down + possibly other errors
if (error.message === 'Internal XMLHttpRequest Error') {
return (
<Container>
<Alert color="danger" style={{ marginTop: '2em' }}>
We encountered some network problems, please refresh.
</Alert>
</Container>
);
}
}
return (
<Container>
<Alert color="danger" style={{ marginTop: '2em' }}>
An unknown error has ocurred, please refresh.
</Alert>
</Container>
);
},
render () {
// If we don't have any data yet, show the loading indicator
if (!this.props.ready) {
return (
<Center height="50vh" data-screen-id="item">
<Spinner />
</Center>
);
}
// When we have the data, render the item view with it
return (
<div data-screen-id="item">
{(this.props.error) ? this.handleError(this.props.error) : (
<div>
<Container>
{
(this.props.currentList.id === 'users'
&& this.state.isAdministrator)
|| this.props.currentList.id !== 'users' ? (
<EditFormHeader
list={this.props.currentList}
data={this.props.data}
toggleCreate={this.toggleCreateModal}
/>
) : null
}
<CreateForm
list={this.props.currentList}
isOpen={this.state.createIsOpen}
onCancel={() => this.toggleCreateModal(false)}
onCreate={(item) => this.onCreate(item)}
/>
<EditForm
list={this.props.currentList}
data={this.props.data}
dispatch={this.props.dispatch}
router={this.context.router}
/>
</Container>
{this.renderRelationships()}
</div>
)}
</div>
);
},
});
module.exports = connect((state) => ({
data: state.item.data,
loading: state.item.loading,
ready: state.item.ready,
error: state.item.error,
currentList: state.lists.currentList,
relationshipData: state.item.relationshipData,
drag: state.item.drag,
}))(ItemView);