Vulcan/packages/vulcan-core/lib/modules/components/Card.jsx
2017-07-25 18:39:26 +09:00

133 lines
No EOL
3.7 KiB
JavaScript

import { registerComponent, Components } from 'meteor/vulcan:lib';
import { intlShape } from 'meteor/vulcan:i18n';
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import moment from 'moment';
import Button from 'react-bootstrap/lib/Button';
const getLabel = (fieldName, collection, intl) => {
const schema = collection.simpleSchema()._schema;
const fieldSchema = schema[fieldName];
return intl.formatMessage({id: `${collection._name}.${fieldName}`, defaultMessage: fieldSchema.label});
}
const getTypeName = (fieldName, collection) => {
const schema = collection.simpleSchema()._schema;
const fieldSchema = schema[fieldName];
const type = fieldSchema.type.singleType;
const typeName = typeof type === 'function' ? type.name : type;
return typeName;
}
const parseImageUrl = value => {
const isImage = ['.png', '.jpg', '.gif'].indexOf(value.substr(-4)) !== -1 || ['.webp', '.jpeg' ].indexOf(value.substr(-5)) !== -1;
return isImage ?
<img style={{width: '100%', maxWidth: 200}} src={value} alt={value}/> :
<LimitedString string={value}/>;
}
const LimitedString = ({ string }) =>
<div>
{string.indexOf(' ') === -1 && string.length > 30 ?
<span title={string}>{string.substr(0,30)}</span> :
<span>{string}</span>
}
</div>
const getFieldValue = (value, typeName) => {
if (!value) {
return ''
}
if (Array.isArray(value)) {
typeName = 'Array';
}
switch (typeName) {
case 'Boolean':
case 'boolean':
case 'Number':
case 'number':
case 'SimpleSchema.Integer':
return <code>{value}</code>;
case 'Array':
return <ol>{value.map((item, index) => <li key={index}>{getFieldValue(item, typeof item)}</li>)}</ol>
case 'Object':
case 'object':
return (
<table className="table">
<tbody>
{_.map(value, (value, key) =>
<tr key={key}>
<td><strong>{key}</strong></td>
<td>{getFieldValue(value, typeof value)}</td>
</tr>
)}
</tbody>
</table>
)
case 'Date':
return moment(new Date(value)).format('dddd, MMMM Do YYYY, h:mm:ss');
default:
return parseImageUrl(value);
}
}
const CardItem = ({label, value, typeName}) =>
<tr>
<td><strong>{label}</strong></td>
<td>{getFieldValue(value, typeName)}</td>
</tr>
const CardEdit = props =>
<tr>
<td colSpan="2">
<Components.ModalTrigger label={<Button bsStyle="default">Edit</Button>}>
<CardEditForm {...props} />
</Components.ModalTrigger>
</td>
</tr>
const CardEditForm = ({ collection, document, closeModal }) =>
<Components.SmartForm
collection={collection}
documentId={document._id}
showRemove={true}
successCallback={document => {
closeModal();
}}
/>
const Card = ({collection, document, currentUser}, {intl}) => {
const fieldNames = _.without(_.keys(document), '__typename', '_id');
const canEdit = currentUser && collection.options.mutations.edit.check(currentUser, document);
return (
<div className={classNames('datacard', `datacard-${collection._name}`)}>
<table className="table table-bordered" style={{maxWidth: '100%'}}>
<tbody>
{canEdit ? <CardEdit collection={collection} document={document} /> : null}
{fieldNames.map((fieldName, index) =>
<CardItem key={index} value={document[fieldName]} typeName={getTypeName(fieldName, collection)} label={getLabel(fieldName, collection, intl)}/>
)}
</tbody>
</table>
</div>
);
};
Card.displayName = "Card";
Card.contextTypes = {
intl: intlShape
}
registerComponent('Card', Card);