meteor-interface
Version:
Simple Content Management System to generate your administration interface for Meteor and React.
270 lines (240 loc) • 10.1 kB
JavaScript
import React, { Fragment, Component, PureComponent } from 'react';
import { withTracker } from 'meteor/react-meteor-data';
import slugify from 'slugify';
import { Transition, Spring } from 'react-spring'
import DynamicImporter from "../../../utils/DynamicImporter";
import { WidgetFormConsumer } from '../../../utils/contexts/WidgetFormContext'
const TinyMCE = DynamicImporter(() => import('react-tinymce'));
// Packages
import {
Segment,
Header,
List,
Label,
Form,
Button,
Checkbox,
Image,
Message,
Icon,
} from 'semantic-ui-react';
import ModalImageSelector from '../../MediaManager/components/ModalImageSelector';
const tinyConfig = {
height: 300,
menubar: false,
plugins: [
'advlist autolink lists link image charmap print preview anchor textcolor colorpicker',
'searchreplace visualblocks code fullscreen',
'insertdatetime media table contextmenu paste code emoticons',
],
toolbar: 'undo redo | insert | fontsizeselect | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link | forecolor backcolor emoticons | image',
};
const WidgetSelector = WidgetFormConsumer((props) => {
let { collection, collection2, item2 } = props
if(item2 && collection2){
collection = collection2
item = item2
}
return collection.fields.map((field, i) => <SingleWidget key={i} field={field} {...props }/> )
})
class SingleWidget extends Component {
state = {
id: Random.id()
}
updateNestedValue = (e, { name, value, checked }) => {
const { nested, index, collection2, item2, parent, context = {}, field } = this.props
let { updateValue, item, collection, ready } = context;
if(item2 && collection2){
collection = collection2
item = item2
}
parent[index][name] = value || checked
updateValue(e, {
name: collection.name ,
value: parent,
})
}
updateNormalValue = (e, { name, value, checked }) => {
const { nested, index, collection2, item2, parent, context = {}, field } = this.props
let { updateValue, item, collection, ready } = context;
updateValue(e, { name, value, checked })
}
incrementeList = (e) => {
const { nested, index, collection2, item2, parent, context = {}, field } = this.props
let { updateValue, item, collection, ready } = context;
if(nested){
parent[index][name] &&
parent[index][name].length ?
parent[index][name].push({})
:
parent[index][name] = [{}]
updateValue(e, {
name: collection.name ,
value: parent,
})
} else {
item[field.name] &&
item[field.name].length ?
item[field.name].push({})
:
item[field.name] = [{}]
updateValue(e, { name: [field.name], value: item[field.name] })
}
}
decrementeList = (e, index) => {
const { nested, collection2, item2, parent, context, field } = this.props;
let { updateValue, item, collection, ready } = context;
if(nested){
parent[index][name].splice(index, 1)
updateValue(e, {
name: collection.name ,
value: parent,
})
} else {
item[field.name].splice(index, 1)
updateValue(e, { name: [field.name], value: item[field.name] })
}
}
render() {
const { id } = this.state
const { nested, index, collection2, item2, parent, context = {}, field } = this.props;
let { updateValue, item, collection, ready } = context;
if(item2 && collection2){
collection = collection2
item = item2
}
switch (field.widget){
case 'string':
return (
<Form.Input
value={item[field.name]}
label={field.label}
key={id}
onChange={ nested ? this.updateNestedValue : this.updateNormalValue}
name={field.name}
/>
)
case 'multiline':
return (
<Form.TextArea
value={item[field.name]}
label={field.label}
key={id}
onChange={ nested ? this.updateNestedValue : this.updateNormalValue}
name={field.name}
/>
)
case 'html':
if(typeof tinymce !== 'undefined'){
return (
<Form.Field className="tinymce-selector">
<label>{field.label}</label>
<div className="wrapper" >
<TinyMCE
content={item[field.name]}
config={tinyConfig}
onChange={e => {
const updateFunction = nested ? this.updateNestedValue : this.updateNormalValue
updateFunction(e, {
name: field.name,
value: e.target.getContent()
})
}}
/>
</div>
</Form.Field>
)
}
return <div key={id}>Loading TinyMCE Editor ... </div>
case 'image':
return (
<Form.Field className="image-selector" key={id} >
<label>{field.label}</label>
<div className="wrapper" >
<Image
rounded
src={item[field.name]}
size="tiny"
/>
<div className="choice" >
<p>{item[field.name]}</p>
<ModalImageSelector
selectPicture={nested ? this.updateNestedValue : this.updateNormalValue}
currentPicture={item[field.name]}
name={field.name}
/>
{item[field.name] &&
<Button
onClick={ nested ? this.updateNestedValue : this.updateNormalValue}
value={null}
name={field.name}
size='mini'
color="red">remove the picture</Button>
}
</div>
</div>
</Form.Field>
)
case 'boolean':
return (
<Form.Field key={id}>
<label>{field.label}</label>
<Checkbox
checked={item[field.name]}
toggle
key={id}
onChange={ nested ? this.updateNestedValue : this.updateNormalValue}
name={field.name}
/>
</Form.Field>
)
case 'list':
if(field.fields){
return (
<Segment key={id} >
<Label as='a' color='green' ribbon size="small">
{field.name}
</Label>
{item[field.name] ? item[field.name].map((mark, i2) => (
<Message key={id + i2}>
<Segment.Group>
<WidgetSelector
collection2={field}
item2={mark}
nested={true}
index={i2}
parent={item[field.name]}
/>
</Segment.Group>
<a className="decrementation" onClick={(e) => this.decrementeList(e, i2)}>Remove</a>
</Message>
)): null }
<a className="incrementation" onClick={this.incrementeList}>Add entry</a>
</Segment>
)
} else {
const options = item[field.name] &&
item[field.name].length > 0 ?
item[field.name].map((mark, i) => ({ key: `${JSON.stringify(mark)}_${i}`, text: mark, value: mark }))
:
[]
return (
<Form.Dropdown
key={id}
name={field.name}
fluid
multiple
label={field.label}
search
selection
allowAdditions
options={options}
onChange={ nested ? this.updateNestedValue : this.updateNormalValue}
value={ item[field.name] || []}
/>
)
}
}
}
}
export default WidgetSelector;