2017-07-25 18:39:26 +09:00
|
|
|
import { registerComponent, Components } from 'meteor/vulcan:lib';
|
2017-07-26 07:30:58 +09:00
|
|
|
import { intlShape, FormattedMessage } from 'meteor/vulcan:i18n';
|
2017-07-25 18:39:26 +09:00
|
|
|
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>
|
|
|
|
|
2017-07-26 07:30:58 +09:00
|
|
|
const CardEdit = (props, context) =>
|
2017-07-25 18:39:26 +09:00
|
|
|
<tr>
|
|
|
|
<td colSpan="2">
|
2017-07-26 07:30:58 +09:00
|
|
|
<Components.ModalTrigger label={context.intl.formatMessage({id: 'cards.edit'})} component={<Button bsStyle="default"><FormattedMessage id="cards.edit" /></Button>}>
|
2017-07-25 18:39:26 +09:00
|
|
|
<CardEditForm {...props} />
|
|
|
|
</Components.ModalTrigger>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
|
2017-07-26 07:30:58 +09:00
|
|
|
CardEdit.contextTypes = { intl: intlShape };
|
|
|
|
|
2017-07-25 18:39:26 +09:00
|
|
|
const CardEditForm = ({ collection, document, closeModal }) =>
|
|
|
|
<Components.SmartForm
|
|
|
|
collection={collection}
|
|
|
|
documentId={document._id}
|
|
|
|
showRemove={true}
|
|
|
|
successCallback={document => {
|
|
|
|
closeModal();
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
|
2017-07-29 09:26:31 +09:00
|
|
|
const Card = ({className, collection, document, currentUser, fields}, {intl}) => {
|
2017-07-25 18:39:26 +09:00
|
|
|
|
2017-07-29 09:26:31 +09:00
|
|
|
const fieldNames = fields ? fields : _.without(_.keys(document), '__typename');
|
2017-07-25 18:39:26 +09:00
|
|
|
const canEdit = currentUser && collection.options.mutations.edit.check(currentUser, document);
|
|
|
|
|
|
|
|
return (
|
2017-07-29 09:26:31 +09:00
|
|
|
<div className={classNames(className, 'datacard', `datacard-${collection._name}`)}>
|
2017-07-25 18:39:26 +09:00
|
|
|
<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";
|
|
|
|
|
2017-07-29 09:26:31 +09:00
|
|
|
Card.propTypes = {
|
|
|
|
className: PropTypes.string,
|
|
|
|
collection: PropTypes.object,
|
|
|
|
document: PropTypes.object,
|
|
|
|
currentUser: PropTypes.object,
|
|
|
|
fields: PropTypes.array,
|
|
|
|
}
|
|
|
|
|
2017-07-25 18:39:26 +09:00
|
|
|
Card.contextTypes = {
|
|
|
|
intl: intlShape
|
|
|
|
}
|
|
|
|
|
|
|
|
registerComponent('Card', Card);
|