mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 01:51:40 -05:00
create vulcan:ui-material, update to Apollo2 RR4
This commit is contained in:
parent
a743022545
commit
b7b872591a
21 changed files with 217 additions and 479 deletions
|
@ -6,7 +6,7 @@ import { STATES } from '../../helpers.js';
|
||||||
|
|
||||||
class AccountsEnrollAccount extends PureComponent {
|
class AccountsEnrollAccount extends PureComponent {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const token = this.props.params.token;
|
const token = this.props.match.params.token;
|
||||||
Accounts._loginButtonsSession.set('enrollAccountToken', token);
|
Accounts._loginButtonsSession.set('enrollAccountToken', token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.js]
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
trim_trailing_whitespace = false
|
|
|
@ -1,86 +0,0 @@
|
||||||
{
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended",
|
|
||||||
//"airbnb",
|
|
||||||
"plugin:meteor/recommended",
|
|
||||||
"plugin:react/recommended"
|
|
||||||
],
|
|
||||||
"parser": "babel-eslint",
|
|
||||||
"parserOptions": {
|
|
||||||
"allowImportExportEverywhere": true,
|
|
||||||
"ecmaVersion": 6,
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"babel/generator-star-spacing": 0,
|
|
||||||
"babel/new-cap": [1, {
|
|
||||||
"capIsNewExceptions": [
|
|
||||||
"Optional",
|
|
||||||
"OneOf",
|
|
||||||
"Maybe",
|
|
||||||
"MailChimpAPI",
|
|
||||||
"Juice",
|
|
||||||
"Run",
|
|
||||||
"AppComposer",
|
|
||||||
"Query",
|
|
||||||
"InArray"
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
"babel/array-bracket-spacing": 0,
|
|
||||||
"babel/object-curly-spacing": 0,
|
|
||||||
"babel/object-shorthand": 0,
|
|
||||||
"babel/arrow-parens": 0,
|
|
||||||
"babel/no-await-in-loop": 1,
|
|
||||||
"comma-dangle": 0,
|
|
||||||
"key-spacing": 0,
|
|
||||||
"no-extra-boolean-cast": 0,
|
|
||||||
"no-undef": 1,
|
|
||||||
"no-unused-vars": [1, {
|
|
||||||
"vars": "all",
|
|
||||||
"args": "none",
|
|
||||||
"varsIgnorePattern": "React|PropTypes|Component"
|
|
||||||
}],
|
|
||||||
"react/prop-types": 0,
|
|
||||||
"react/display-name": 0,
|
|
||||||
"meteor/audit-argument-checks": 0,
|
|
||||||
"meteor/no-session": 0,
|
|
||||||
"no-case-declarations": 0,
|
|
||||||
"no-console": 0,
|
|
||||||
"semi": "error",
|
|
||||||
"quotes": [
|
|
||||||
1,
|
|
||||||
"single"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"commonjs": true,
|
|
||||||
"es6": true,
|
|
||||||
"meteor": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"babel",
|
|
||||||
"meteor",
|
|
||||||
"react",
|
|
||||||
"jsx-a11y"
|
|
||||||
],
|
|
||||||
"settings": {
|
|
||||||
"import/resolver": {
|
|
||||||
"meteor": {
|
|
||||||
"paths": [
|
|
||||||
"/usr/local/share/global_modules"
|
|
||||||
],
|
|
||||||
"moduleDirectory": [
|
|
||||||
"node_modules",
|
|
||||||
"packages"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": true,
|
|
||||||
"globals": {
|
|
||||||
"param": true,
|
|
||||||
"returns": true
|
|
||||||
}
|
|
||||||
}
|
|
3
packages/vulcan-ui-material/.gitignore
vendored
3
packages/vulcan-ui-material/.gitignore
vendored
|
@ -1,3 +1,6 @@
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
node_modules
|
node_modules
|
||||||
.idea/workspace.xml
|
.idea/workspace.xml
|
||||||
|
|
||||||
|
### eslint-config
|
||||||
|
.eslintrc
|
||||||
|
|
|
@ -4,31 +4,40 @@ import { Components, registerComponent } from 'meteor/vulcan:core';
|
||||||
import { intlShape } from 'meteor/vulcan:i18n';
|
import { intlShape } from 'meteor/vulcan:i18n';
|
||||||
import EditIcon from 'mdi-material-ui/Pencil';
|
import EditIcon from 'mdi-material-ui/Pencil';
|
||||||
|
|
||||||
|
const EditButton = (
|
||||||
const EditButton = ({
|
{
|
||||||
collection,
|
collection,
|
||||||
document,
|
document,
|
||||||
color = 'default',
|
color = 'default',
|
||||||
variant,
|
variant,
|
||||||
triggerClasses,
|
triggerClasses,
|
||||||
buttonClasses,
|
buttonClasses,
|
||||||
|
showRemove,
|
||||||
...props
|
...props
|
||||||
}, { intl }) => (
|
},
|
||||||
|
{ intl }
|
||||||
|
) => (
|
||||||
<Components.ModalTrigger
|
<Components.ModalTrigger
|
||||||
classes={triggerClasses}
|
classes={triggerClasses}
|
||||||
component={<Components.TooltipIconButton titleId="datatable.edit"
|
component={
|
||||||
|
<Components.TooltipIconButton
|
||||||
|
titleId="datatable.edit"
|
||||||
icon={<EditIcon />}
|
icon={<EditIcon />}
|
||||||
color={color}
|
color={color}
|
||||||
variant={variant}
|
variant={variant}
|
||||||
classes={buttonClasses}
|
classes={buttonClasses}
|
||||||
/>}
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<Components.EditForm collection={collection} document={document} {...props}/>
|
<Components.EditForm
|
||||||
|
collection={collection}
|
||||||
|
document={document}
|
||||||
|
showRemove={showRemove}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
</Components.ModalTrigger>
|
</Components.ModalTrigger>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
EditButton.propTypes = {
|
EditButton.propTypes = {
|
||||||
collection: PropTypes.object.isRequired,
|
collection: PropTypes.object.isRequired,
|
||||||
document: PropTypes.object.isRequired,
|
document: PropTypes.object.isRequired,
|
||||||
|
@ -36,27 +45,32 @@ EditButton.propTypes = {
|
||||||
variant: PropTypes.string,
|
variant: PropTypes.string,
|
||||||
triggerClasses: PropTypes.object,
|
triggerClasses: PropTypes.object,
|
||||||
buttonClasses: PropTypes.object,
|
buttonClasses: PropTypes.object,
|
||||||
|
showRemove: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
EditButton.contextTypes = {
|
EditButton.contextTypes = {
|
||||||
intl: intlShape
|
intl: intlShape
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
EditButton.displayName = 'EditButton';
|
EditButton.displayName = 'EditButton';
|
||||||
|
|
||||||
|
|
||||||
registerComponent('EditButton', EditButton);
|
registerComponent('EditButton', EditButton);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
EditForm Component
|
EditForm Component
|
||||||
|
|
||||||
*/
|
*/
|
||||||
const EditForm = ({ collection, document, closeModal, options, successCallback, removeSuccessCallback,...props }) => {
|
const EditForm = ({
|
||||||
|
collection,
|
||||||
|
document,
|
||||||
|
closeModal,
|
||||||
|
options,
|
||||||
|
successCallback,
|
||||||
|
removeSuccessCallback,
|
||||||
|
showRemove,
|
||||||
|
...props
|
||||||
|
}) => {
|
||||||
const success = successCallback
|
const success = successCallback
|
||||||
? () => {
|
? () => {
|
||||||
successCallback();
|
successCallback();
|
||||||
|
@ -76,11 +90,11 @@ const EditForm = ({ collection, document, closeModal, options, successCallback,
|
||||||
{...props}
|
{...props}
|
||||||
collection={collection}
|
collection={collection}
|
||||||
documentId={document && document._id}
|
documentId={document && document._id}
|
||||||
showRemove={true}
|
showRemove={showRemove ? true : showRemove}
|
||||||
successCallback={success}
|
successCallback={success}
|
||||||
removeSuccessCallback={remove}
|
removeSuccessCallback={remove}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
registerComponent('EditForm', EditForm);
|
registerComponent('EditForm', EditForm);
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { intlShape } from 'meteor/vulcan:i18n';
|
import { intlShape } from 'meteor/vulcan:i18n';
|
||||||
import { registerComponent } from 'meteor/vulcan:core';
|
import { registerComponent, Components } from 'meteor/vulcan:core';
|
||||||
import withStyles from '@material-ui/core/styles/withStyles';
|
import withStyles from '@material-ui/core/styles/withStyles';
|
||||||
import Dialog from '@material-ui/core/Dialog';
|
import Dialog from '@material-ui/core/Dialog';
|
||||||
import DialogContent from '@material-ui/core/DialogContent';
|
|
||||||
import DialogTitle from '@material-ui/core/DialogTitle';
|
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||||
|
import DialogContent from '@material-ui/core/DialogContent';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
|
import Close from 'mdi-material-ui/Close';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,25 +20,27 @@ const styles = theme => ({
|
||||||
button: {},
|
button: {},
|
||||||
anchor: {},
|
anchor: {},
|
||||||
dialog: {},
|
dialog: {},
|
||||||
dialogPaper: {},
|
dialogPaper: {
|
||||||
dialogTitle: {},
|
overflowY: 'visible',
|
||||||
|
},
|
||||||
|
dialogTitle: {
|
||||||
|
padding: theme.spacing.unit * 4,
|
||||||
|
},
|
||||||
dialogContent: {
|
dialogContent: {
|
||||||
paddingTop: '4px',
|
paddingTop: '4px',
|
||||||
},
|
},
|
||||||
dialogOverflow: {
|
closeButton: {
|
||||||
overflowY: 'visible',
|
position: 'absolute',
|
||||||
},
|
right: theme.spacing.unit,
|
||||||
|
top: theme.spacing.unit,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
class ModalTrigger extends PureComponent {
|
class ModalTrigger extends PureComponent {
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = { modalIsOpen: false };
|
this.state = { modalIsOpen: false };
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -92,24 +97,28 @@ class ModalTrigger extends PureComponent {
|
||||||
<span className={classNames('modal-trigger', classes.root, className)}>
|
<span className={classNames('modal-trigger', classes.root, className)}>
|
||||||
|
|
||||||
{triggerComponent}
|
{triggerComponent}
|
||||||
|
|
||||||
<Dialog className={classNames(dialogClassName)}
|
<Dialog className={classNames(dialogClassName)}
|
||||||
open={this.state.modalIsOpen}
|
open={this.state.modalIsOpen}
|
||||||
onClose={this.closeModal}
|
onClose={this.closeModal}
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
classes={{ paper: classNames(classes.dialogPaper, overflowClass) }}
|
classes={{ paper: classes.paper }}
|
||||||
>
|
>
|
||||||
|
<DialogTitle className={classes.dialogTitle}>
|
||||||
|
{title}
|
||||||
|
|
||||||
{
|
<Components.Button iconButton aria-label="Close" className={classes.closeButton} onClick={this.closeModal}>
|
||||||
title &&
|
<Tooltip title={intl.formatMessage({ id: 'modal.close' })}>
|
||||||
|
<Close />
|
||||||
|
</Tooltip>
|
||||||
|
</Components.Button>
|
||||||
|
|
||||||
<DialogTitle className={classes.dialogTitle}>{title}</DialogTitle>
|
</DialogTitle>
|
||||||
}
|
|
||||||
|
|
||||||
<DialogContent className={classNames(classes.dialogContent, overflowClass)}>
|
<DialogContent className={classes.dialogContent}>
|
||||||
|
<Components.ErrorCatcher>
|
||||||
{childrenComponent}
|
{childrenComponent}
|
||||||
|
</Components.ErrorCatcher>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -118,7 +118,7 @@ FormComponentInner.propTypes = {
|
||||||
showCharsRemaining: PropTypes.bool.isRequired,
|
showCharsRemaining: PropTypes.bool.isRequired,
|
||||||
charsRemaining: PropTypes.number,
|
charsRemaining: PropTypes.number,
|
||||||
charsCount: PropTypes.number,
|
charsCount: PropTypes.number,
|
||||||
max: PropTypes.number,
|
max: PropTypes.oneOfType([PropTypes.number, PropTypes.instanceOf(Date)]),
|
||||||
formInput: PropTypes.func.isRequired,
|
formInput: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,205 +0,0 @@
|
||||||
import React, { PureComponent } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Components, replaceComponent, instantiateComponent, } from 'meteor/vulcan:core';
|
|
||||||
import Users from 'meteor/vulcan:users';
|
|
||||||
import withStyles from '@material-ui/core/styles/withStyles';
|
|
||||||
import Collapse from '@material-ui/core/Collapse';
|
|
||||||
import Typography from '@material-ui/core/Typography';
|
|
||||||
import Paper from '@material-ui/core/Paper';
|
|
||||||
import ExpandLessIcon from 'mdi-material-ui/ChevronUp';
|
|
||||||
import ExpandMoreIcon from 'mdi-material-ui/ChevronDown';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
|
|
||||||
const styles = theme => ({
|
|
||||||
root: {
|
|
||||||
minWidth: '320px'
|
|
||||||
},
|
|
||||||
paper: {
|
|
||||||
padding: theme.spacing.unit * 3
|
|
||||||
},
|
|
||||||
subtitle1: {
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
paddingLeft: theme.spacing.unit / 2,
|
|
||||||
marginTop: theme.spacing.unit * 5,
|
|
||||||
marginBottom: theme.spacing.unit,
|
|
||||||
color: theme.palette.primary[500],
|
|
||||||
},
|
|
||||||
collapsible: {
|
|
||||||
cursor: 'pointer',
|
|
||||||
},
|
|
||||||
label: {},
|
|
||||||
toggle: {
|
|
||||||
'& svg': {
|
|
||||||
width: 21,
|
|
||||||
height: 21,
|
|
||||||
display: 'block',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
container: {
|
|
||||||
paddingLeft: 4,
|
|
||||||
paddingRight: 4,
|
|
||||||
marginLeft: -4,
|
|
||||||
marginRight: -4,
|
|
||||||
},
|
|
||||||
entered: {
|
|
||||||
overflow: 'visible',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
class FormGroup extends PureComponent {
|
|
||||||
|
|
||||||
|
|
||||||
constructor (props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.isAdmin = props.name === 'admin';
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
collapsed: props.startCollapsed || this.isAdmin,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
toggle = () => {
|
|
||||||
const collapsible = this.props.collapsible || this.isAdmin;
|
|
||||||
if (!collapsible) return;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
collapsed: !this.state.collapsed
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
renderHeading = () => {
|
|
||||||
const { classes, label } = this.props;
|
|
||||||
const collapsible = this.props.collapsible || this.isAdmin;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Typography className={classNames(classes.subtitle1, collapsible && classes.collapsible)}
|
|
||||||
variant="subtitle1"
|
|
||||||
onClick={this.toggle}
|
|
||||||
>
|
|
||||||
|
|
||||||
<div className={classes.label}>
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
collapsible &&
|
|
||||||
|
|
||||||
<div className={classes.toggle}>
|
|
||||||
{
|
|
||||||
this.state.collapsed
|
|
||||||
?
|
|
||||||
<ExpandMoreIcon/>
|
|
||||||
:
|
|
||||||
<ExpandLessIcon/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
</Typography>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// if at least one of the fields in the group has an error, the group as a whole has an error
|
|
||||||
hasErrors = () => _.some(this.props.fields, field => {
|
|
||||||
return !!this.props.errors.filter(error => error.path === field.path).length;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
hidden,
|
|
||||||
classes,
|
|
||||||
currentUser,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
if (this.isAdmin && !Users.isAdmin(currentUser)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof hidden === 'function' ? hidden({ ...this.props }) : hidden) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//do not display if no fields, no startComponent and no endComponent
|
|
||||||
if (!this.props.startComponent && !this.props.endComponent && !this.props.fields.length) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const anchorName = name.split('.').length > 1 ? name.split('.')[1] : name;
|
|
||||||
const collapseIn = !this.state.collapsed || this.hasErrors();
|
|
||||||
|
|
||||||
const FormComponents = this.props.formComponents;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={classes.root}>
|
|
||||||
|
|
||||||
<a name={anchorName}/>
|
|
||||||
|
|
||||||
{
|
|
||||||
name === 'default'
|
|
||||||
?
|
|
||||||
null
|
|
||||||
:
|
|
||||||
this.renderHeading()
|
|
||||||
}
|
|
||||||
|
|
||||||
<Collapse classes={{ container: classes.container, entered: classes.entered }} in={collapseIn}>
|
|
||||||
<Paper className={classes.paper}>
|
|
||||||
|
|
||||||
{instantiateComponent(this.props.startComponent)}
|
|
||||||
|
|
||||||
{this.props.fields.map(field => (
|
|
||||||
<FormComponents.FormComponent
|
|
||||||
key={field.name}
|
|
||||||
disabled={this.props.disabled}
|
|
||||||
{...field}
|
|
||||||
errors={this.props.errors}
|
|
||||||
throwError={this.props.throwError}
|
|
||||||
currentValues={this.props.currentValues}
|
|
||||||
updateCurrentValues={this.props.updateCurrentValues}
|
|
||||||
deletedValues={this.props.deletedValues}
|
|
||||||
addToDeletedValues={this.props.addToDeletedValues}
|
|
||||||
clearFieldErrors={this.props.clearFieldErrors}
|
|
||||||
formType={this.props.formType}
|
|
||||||
currentUser={this.props.currentUser}
|
|
||||||
formComponents={FormComponents}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{instantiateComponent(this.props.endComponent)}
|
|
||||||
|
|
||||||
</Paper>
|
|
||||||
</Collapse>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FormGroup.propTypes = {
|
|
||||||
name: PropTypes.string,
|
|
||||||
label: PropTypes.string,
|
|
||||||
order: PropTypes.number,
|
|
||||||
hidden: PropTypes.bool,
|
|
||||||
fields: PropTypes.array,
|
|
||||||
collapsible: PropTypes.bool,
|
|
||||||
startCollapsed: PropTypes.bool,
|
|
||||||
updateCurrentValues: PropTypes.func,
|
|
||||||
startComponent: PropTypes.node,
|
|
||||||
endComponent: PropTypes.node,
|
|
||||||
currentUser: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
replaceComponent('FormGroup', FormGroup, [withStyles, styles]);
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { replaceComponent } from 'meteor/vulcan:core';
|
||||||
|
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
|
||||||
|
const FormNestedArrayLayout = ({ hasErrors, label, content }) => (
|
||||||
|
<div>
|
||||||
|
<Typography component="label" variant="caption" style={{ fontSize: 16 }}>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
<div>{content}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
FormNestedArrayLayout.propTypes = {
|
||||||
|
hasErrors: PropTypes.bool,
|
||||||
|
label: PropTypes.node,
|
||||||
|
content: PropTypes.node,
|
||||||
|
};
|
||||||
|
replaceComponent({
|
||||||
|
name: 'FormNestedArrayLayout',
|
||||||
|
component: FormNestedArrayLayout,
|
||||||
|
});
|
|
@ -1,23 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { registerComponent } from 'meteor/vulcan:core';
|
import { replaceComponent } from 'meteor/vulcan:core';
|
||||||
import { FormattedMessage } from 'meteor/vulcan:i18n';
|
// import { FormattedMessage } from 'meteor/vulcan:i18n';
|
||||||
import withStyles from '@material-ui/core/styles/withStyles';
|
import withStyles from '@material-ui/core/styles/withStyles';
|
||||||
import Divider from '@material-ui/core/Divider';
|
import Divider from '@material-ui/core/Divider';
|
||||||
|
|
||||||
|
|
||||||
const styles = theme => ({
|
const styles = theme => ({
|
||||||
|
|
||||||
divider: {
|
divider: {
|
||||||
marginLeft: -24,
|
// marginLeft: -24,
|
||||||
marginRight: -24,
|
// marginRight: -24,
|
||||||
marginTop: 16,
|
marginTop: 16,
|
||||||
marginBottom: 23,
|
marginBottom: 23,
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const FormNestedDivider = ({ classes, label, addItem }) => <Divider className={classes.divider} />;
|
const FormNestedDivider = ({ classes, label, addItem }) => <Divider className={classes.divider} />;
|
||||||
|
|
||||||
FormNestedDivider.propTypes = {
|
FormNestedDivider.propTypes = {
|
||||||
|
@ -26,4 +22,4 @@ FormNestedDivider.propTypes = {
|
||||||
addItem: PropTypes.func,
|
addItem: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
registerComponent('FormNestedDivider', FormNestedDivider, [withStyles, styles]);
|
replaceComponent('FormNestedDivider', FormNestedDivider, [withStyles, styles]);
|
||||||
|
|
|
@ -5,8 +5,8 @@ import { FormattedMessage } from 'meteor/vulcan:i18n';
|
||||||
import Grid from '@material-ui/core/Grid';
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
|
||||||
const FormNestedFoot = ({ label, addItem }) => (
|
const FormNestedFoot = ({ label, addItem }) => (
|
||||||
<Grid container spacin={0} justify="flex-end">
|
<Grid container spacing={0} justify="flex-end">
|
||||||
<Components.Button color="primary" variant="fab" mini onClick={addItem} className="form-nested-add">
|
<Components.Button color="primary" iconButton onClick={addItem}>
|
||||||
<Components.IconAdd/>
|
<Components.IconAdd/>
|
||||||
</Components.Button>
|
</Components.Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -73,11 +73,7 @@ const MuiRadioGroup = createReactClass({
|
||||||
options: PropTypes.array.isRequired
|
options: PropTypes.array.isRequired
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function () {
|
|
||||||
if (this.props.refFunction) {
|
|
||||||
this.props.refFunction(this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultProps: function () {
|
getDefaultProps: function () {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -105,6 +105,7 @@ export default {
|
||||||
'description',
|
'description',
|
||||||
'clearField',
|
'clearField',
|
||||||
'regEx',
|
'regEx',
|
||||||
|
'allowedValues',
|
||||||
'mustComplete',
|
'mustComplete',
|
||||||
'renderComponent',
|
'renderComponent',
|
||||||
'formInput',
|
'formInput',
|
||||||
|
|
|
@ -7,7 +7,7 @@ import './accounts/AccountsPasswordOrService';
|
||||||
import './accounts/AccountsSocialButtons';
|
import './accounts/AccountsSocialButtons';
|
||||||
|
|
||||||
import './bonus/LoadMore';
|
import './bonus/LoadMore';
|
||||||
import './bonus/SearchInput';
|
// import './bonus/SearchInput';
|
||||||
import './bonus/TooltipIntl';
|
import './bonus/TooltipIntl';
|
||||||
import './bonus/TooltipIconButton';
|
import './bonus/TooltipIconButton';
|
||||||
|
|
||||||
|
@ -20,10 +20,11 @@ import './core/NewButton';
|
||||||
|
|
||||||
import './forms/FormComponentInner';
|
import './forms/FormComponentInner';
|
||||||
import './forms/FormErrors';
|
import './forms/FormErrors';
|
||||||
import './forms/FormGroup';
|
//import './forms/FormGroup';
|
||||||
import './forms/FormGroupNone';
|
import './forms/FormGroupNone';
|
||||||
import './forms/FormGroupWithLine';
|
import './forms/FormGroupWithLine';
|
||||||
import './forms/FormNested';
|
import './forms/FormNested';
|
||||||
|
import './forms/FormNestedArrayLayout';
|
||||||
import './forms/FormNestedDivider';
|
import './forms/FormNestedDivider';
|
||||||
import './forms/FormNestedFoot';
|
import './forms/FormNestedFoot';
|
||||||
import './forms/FormNestedHead';
|
import './forms/FormNestedHead';
|
||||||
|
|
|
@ -3,10 +3,10 @@ import { addStrings } from 'meteor/vulcan:core';
|
||||||
|
|
||||||
addStrings('en', {
|
addStrings('en', {
|
||||||
|
|
||||||
"search.search": "Search",
|
'search.search': 'Search',
|
||||||
"search.clear": "Clear search",
|
'search.clear': 'Clear search',
|
||||||
"load_more.load_more": "Load more",
|
'load_more.load_more': 'Load more',
|
||||||
"load_more.loaded_count": "Loaded {count} of {totalCount}",
|
'load_more.loaded_count': 'Loaded {count} of {totalCount}',
|
||||||
"load_more.loaded_all": "{totalCount, plural, =0 {No items} one {One item} other {# items}}",
|
'load_more.loaded_all': '{totalCount, plural, =0 {No items} one {One item} other {# items}}',
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -74,6 +74,7 @@ const styles = theme => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Layout extends React.Component {
|
class Layout extends React.Component {
|
||||||
state = {
|
state = {
|
||||||
isOpen: { sideNav: true }
|
isOpen: { sideNav: true }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Components, registerComponent, withCurrentUser } from 'meteor/vulcan:core';
|
import { Components, registerComponent, withCurrentUser } from 'meteor/vulcan:core';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router';
|
||||||
import List from '@material-ui/core/List';
|
import List from '@material-ui/core/List';
|
||||||
import ListItem from '@material-ui/core/ListItem';
|
import ListItem from '@material-ui/core/ListItem';
|
||||||
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||||
|
@ -38,15 +38,14 @@ class SideNavigation extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const currentUser = this.props.currentUser;
|
const { currentUser, classes, history } = this.props;
|
||||||
const classes = this.props.classes;
|
|
||||||
const isOpen = this.state.isOpen;
|
const isOpen = this.state.isOpen;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
|
|
||||||
<List>
|
<List>
|
||||||
<ListItem button onClick={() => {this.props.history.push('/');}}>
|
<ListItem button onClick={() => {history.push('/');}}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<HomeIcon/>
|
<HomeIcon/>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
|
@ -69,14 +68,14 @@ class SideNavigation extends React.Component {
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<Collapse in={isOpen.admin} transitionduration="auto" unmountOnExit>
|
<Collapse in={isOpen.admin} transitionduration="auto" unmountOnExit>
|
||||||
<ListItem button className={classes.nested}
|
<ListItem button className={classes.nested}
|
||||||
onClick={() => {this.props.history.push('/admin');}}>
|
onClick={() => {browserHistory.push('/admin');}}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<UsersIcon/>
|
<UsersIcon/>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText inset primary="Users"/>
|
<ListItemText inset primary="Users"/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem button className={classes.nested}
|
<ListItem button className={classes.nested}
|
||||||
onClick={() => {this.props.history.push('/theme');}}>
|
onClick={() => {browserHistory.push('/theme');}}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<ThemeIcon/>
|
<ThemeIcon/>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { addStrings } from 'meteor/vulcan:core';
|
import { addStrings } from 'meteor/vulcan:core';
|
||||||
|
|
||||||
addStrings('fr', {
|
addStrings('fr', {
|
||||||
|
'search.search': 'Recherche',
|
||||||
"search.search": "Recherche",
|
'search.clear': 'Effacer la recherche',
|
||||||
"search.clear": "Effacer la recherche",
|
'modal.close': 'Fermer',
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { addRoute } from 'meteor/vulcan:core';
|
import { addRoute } from 'meteor/vulcan:core';
|
||||||
|
|
||||||
|
//Only create route on dev mode, not production.
|
||||||
|
if (Meteor.isDevelopment) {
|
||||||
addRoute({
|
addRoute({
|
||||||
name: 'theme',
|
name: 'theme',
|
||||||
path: '/theme',
|
path: '/theme',
|
||||||
componentName: 'ThemeStyles',
|
componentName: 'ThemeStyles',
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ Package.describe({
|
||||||
documentation: 'README.md'
|
documentation: 'README.md'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Package.onUse(function (api) {
|
Package.onUse(function (api) {
|
||||||
api.versionsFrom('METEOR@1.6');
|
api.versionsFrom('METEOR@1.6');
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
# erikdakoda:vulcan-material-ui 1.12.8_13
|
# vulcan:ui-material 1.12.8_13
|
||||||
|
|
||||||
|
Package initially created by [Erik Dakoda](https://github.com/ErikDakoda) ([`erikdakoda:vulcan-material-ui`](https://github.com/ErikDakoda/vulcan-material-ui))
|
||||||
|
|
||||||
|
|
||||||
Replacement for [Vulcan](http://vulcanjs.org/) components using [Material-UI](https://material-ui.com/).
|
Replacement for [Vulcan](http://vulcanjs.org/) components using [Material-UI](https://material-ui.com/).
|
||||||
This version has been tested against Vulcan 1.12.8 and Material-UI 3.1.0.
|
|
||||||
|
|
||||||
To give me feedback open an issue on GitHub or you can reach me on the [Vulcan Slack](https://vulcanjs.slack.com)
|
|
||||||
channel as erikdakoda.
|
|
||||||
|
|
||||||
There are some nice bonus features like a CountrySelect with autocomplete and theming.
|
There are some nice bonus features like a CountrySelect with autocomplete and theming.
|
||||||
|
|
||||||
|
@ -15,9 +15,9 @@ All components in vulcan:ui-bootstrap, vulcan:forms and vulcan:accounts have bee
|
||||||
To add vulcan-material-ui to an existing Vulcan project, enter the following:
|
To add vulcan-material-ui to an existing Vulcan project, enter the following:
|
||||||
|
|
||||||
``` sh
|
``` sh
|
||||||
meteor add erikdakoda:vulcan-material-ui
|
meteor add vulcan:ui-material
|
||||||
|
|
||||||
meteor npm install --save @material-ui/core
|
meteor npm install --save @material-ui/core@3.1.0
|
||||||
meteor npm install --save react-jss
|
meteor npm install --save react-jss
|
||||||
meteor npm install --save mdi-material-ui
|
meteor npm install --save mdi-material-ui
|
||||||
meteor npm install --save react-autosuggest
|
meteor npm install --save react-autosuggest
|
||||||
|
@ -48,7 +48,7 @@ For an example theme see `modules/sampleTheme.js`. For a complete list of values
|
||||||
see the [MUI Default Theme](https://material-ui-next.com/customization/default-theme/).
|
see the [MUI Default Theme](https://material-ui-next.com/customization/default-theme/).
|
||||||
|
|
||||||
Register your theme in the Vulcan environment by giving it a name: `registerTheme('MyTheme', theme);`.
|
Register your theme in the Vulcan environment by giving it a name: `registerTheme('MyTheme', theme);`.
|
||||||
You can have multiple themes registered and you can specify which one to use in your settings file using the `muiTheme` public setting.
|
You can have multiple themes registered and you can specify which one to use in your settings file using the `muiTheme` **public** setting.
|
||||||
|
|
||||||
In addition to the Material UI spec, I use a `utils` section in my themes where I place global variables for reusable styles.
|
In addition to the Material UI spec, I use a `utils` section in my themes where I place global variables for reusable styles.
|
||||||
For example the sample theme contains
|
For example the sample theme contains
|
||||||
|
|
Loading…
Add table
Reference in a new issue