Files
bukopin-redemption-client-r…/src/common/pages/ContentManager/Form/index.js

734 lines
25 KiB
JavaScript

import React from 'react';
import {observer, inject} from 'mobx-react';
import {
Card,
FlatButton,
Divider,
RaisedButton,
Toolbar,
MenuItem,
ToolbarGroup,
IconButton,
ToolbarTitle,
Dialog,
Toggle
} from 'material-ui';
import DeleteIcon from 'material-ui/svg-icons/action/delete';
import {Icon, Input, Select, message, Button as ButtonAntd, Affix,TreeSelect} from 'antd'
import {LINKS} from "../../../routes";
const Option = Select.Option;
const TreeNode = TreeSelect.TreeNode;
import {lowerCase,debounce} from 'lodash';
// Require Editor JS files.
// import 'froala-editor/js/froala_editor.pkgd.min.js';
// Require Editor CSS files.
// import 'froala-editor/css/froala_style.min.css';
// import 'froala-editor/css/froala_editor.pkgd.min.css';
const $ = require("jquery");
// require("froala-editor/js/froala_editor.pkgd.min.js")($);
window.$ = window.jQuery = $;
// require("froala-editor/js/froala_editor.pkgd.min.js")($);
// require("froala-editor/js/plugins/code_view.min.js")($);
// window.$ = window.jQuery = $;
import 'froala-editor/css/froala_style.min.css';
import 'froala-editor/css/froala_editor.pkgd.min.css';
// import 'froala-editor/css/plugins/code_view.min.css';
// Require Font Awesome.
import 'font-awesome/css/font-awesome.css';
import FroalaEditor from 'react-froala-wysiwyg';
@inject('appstate')
@observer
export default class Form extends React.Component {
constructor(props) {
super(props);
this.props = props;
this.rewardStore = props.appstate.reward;
this.state = {
openedDialogEmpty:false,
featured_media_exist: false,
text: '',
openedDialog: false,
openDeleteDialog : false,
saveButton: true,
value: 1,
isFree : false,
searchText: '',
slideIndex: 0,
openedDialogBack: false,
reward_type: "Choose Reward Type",
expanded: false,
previewVisible: false,
previewImage: '',
fileList: [],
fileLength: 0,
fileMainExist: false,
visible:false,
formData: {
//tags: ['a571f41f-c9d2-4fe1-9638-320c589cffe3'],
tags: [],
additional_data : {
items: []
}
},
disabled_price : false,
mode: 'create',
html : "",
config: {
placeholderText: 'Edit Your Content Here!',
charCounterCount: true,
toolbarStickyOffset: 73,
toolbarButtons: ['insertLink', 'bold', 'italic', 'underline', 'fontFamily', 'fontSize', 'color', 'align', 'formatOL', 'formatUL', 'embedly', '|', 'insertImage', 'insertVideo', 'insertFile', '|', 'help'],
quickInsertButtons: ['embedly','hr', 'image', 'video'],
codeBeautifierOptions: {
end_with_newline: true,
indent_inner_html: true,
extra_liners: "['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre', 'ul', 'ol', 'table', 'dl']",
brace_style: 'expand',
indent_char: ' ',
indent_size: 4,
wrap_line_length: 0
},
heightMin: '50vh'
}
};
this.defaultState = Object.assign({}, this.state);
this.http = props.appstate.http;
this.authStore = props.appstate.auth;
this.globalUI = props.appstate.globalUI;
this.categoryStore = props.appstate.category;
this.itemStore = props.appstate.item;
this.myStoreItem = props.appstate.myStoreItem;
this.contentManagerStore = props.appstate.contentManager;
this.editor = null;
this.userData = props.appstate.userData;
}
async componentDidMount() {
console.log(this.props.match.params.id,'ini id params')
window.scrollTo(0, 0);
this.contentManagerStore.getTags();
// this.contentManagerStore.getTypes();
this.contentManagerStore.clearItems();
if(this.props.match.params.id){
this.contentManagerStore.getDetail(this.props.match.params.id).then(res => {
console.log(this.contentManagerStore.selected.title,this.contentManagerStore.selected.content,'res detail')
let newArray = this.contentManagerStore.selected.additional_data.items.map(it => it);
let newTagsArray =this.contentManagerStore.selected.tags.map(it => it);
console.log(newTagsArray[0].tag_id,'newTagsArray');
if(newArray.length>0){
this.contentManagerStore.loadItems(newArray);
}
let data;
data = {
title:this.contentManagerStore.selected.title,
type:this.contentManagerStore.selected.type,
content:this.contentManagerStore.selected.content,
tags:[newTagsArray[0].tag_id],
additional_data:{
items: newArray
}
}
this.setState({
formData : data,
text : this.contentManagerStore.selected.content,
});
if(newTagsArray[0].tag_id == 'b0819754-fb35-4e52-be67-eb76ca80c5a4'){
this.setState({
visible:true
})
}
// console.log("new formmm",this.state.formData,this.state.text)
});
// console.log("new formmm items",this.state.formData.additional_data.items)
}
// $('.fr-wrapper').children[0].style.display = 'none';
// setTimeout(() => {
// $('.fr-wrapper').children[0].style.display = 'none';
// }, 1000);
}
handleModelChange = (model) => {
this.setState({
text: model
});
};
handleCancel = () => this.setState({ previewVisible: false });
handleOpen = () => {
console.log(this.state.html,'heree');
this.setState({openedDialog: true});
};
handleClose = () => {
this.setState({openedDialog: false});
};
goToClassDetail(){
this.props.history.push(`${LINKS.CLASSES}/${this.props.match.params.id}`);
}
postData = () => {
console.log("post!!!", this.state.formData);
if(!this.state.formData.title || this.state.formData.title=="" || !this.state.text || this.state.text==""){
message.success('Title and content cannot be empty!');
console.log('inikosongdatanya')
this.setState({openedDialog: false});
this.setState({openedDialogEmpty:true});
}
else{
this.setState({openedDialog: false});
this.globalUI.openLoading();
const data=Object.assign({},this.state.formData);
data.content=this.state.text;
// if(typeof data.price === "string"){
// data.price = new DC(data.price.replace(/\,/g,"")).toFixed();
// }
console.log("data",data);
this.contentManagerStore.post(data)
.then(res => {
this.globalUI.hideDialogLoading();
this.globalUI.openSnackbar("Success Added New Content");
this.props.history.push(LINKS.CONTENT);
})
.catch(err => {
this.globalUI.openSnackbar(err.message);
console.error(err, 'ini errornya');
});
}
};
deleteData = () => {
};
searchItem = ()=>{
console.log('do search');
};
editData = () => {
console.log("Edit!!!", this.state.formData);
if(!this.state.formData.title || this.state.formData.title=="" || !this.state.text || this.state.text==""){
console.log('inikosongdatanya')
this.setState({openedDialog: false});
this.setState({openedDialogEmpty:true});
}
else{
this.globalUI.openLoading();
this.setState({openedDialog: false});
const data=Object.assign({},this.state.formData);
data.content=this.state.text;
console.log("data",data);
this.contentManagerStore.put(this.props.match.params.id,data)
.then(res => {
this.globalUI.hideDialogLoading();
this.globalUI.openSnackbar("Success Edit Content");
this.props.history.push(LINKS.CONTENT_MANAGER);
})
.catch(err => {
this.globalUI.openSnackbar(err.message);
console.error(err, 'ini errornya');
});
}
};
handleBackClose = () => {
this.setState({openedDialogBack: false})
};
handleEmptyClose = () => {
this.setState({openedDialogEmpty: false})
};
handleEmptyOpen = () => {
this.setState({openedDialogEmpty: true})
};
handleBackOpen = () => {
this.setState({openedDialogBack: true});
};
inputContent = (evt)=>{
// console.log(evt.target.value);
this.setState({
html : evt.target.value
})
}
handleChange = ({ fileList }) => {this.setState({ fileList }); console.log(fileList, 'remove')};
uploaderHandler({file, onProgress}) {
console.log(file, 'upload');
console.log("fileLength", this.state.fileLength);
console.log("fileMainExist", this.state.fileMainExist);
this.http.upload(file)
.then(res => {
const {fileList} = this.state;
let newFileList = fileList.filter((obj)=>{
if(!obj.lastModified){
return true;
}
})
if(!this.state.fileMainExist){
newFileList.push({
uid: newFileList.length,
name: file.name,
status: 'done',
url: this.http.appendImagePath(res.path),
path: res.path,
type: 'main'
});
}
else{
newFileList.push({
uid: newFileList.length,
name: file.name,
status: 'done',
url: this.http.appendImagePath(res.path),
path: res.path,
type: 'gallery'
});
}
console.log("update fileList",fileList);
console.log("new fileList",newFileList);
this.setState({fileList : newFileList});
})
}
handleWarningDialog = (bool)=>{
this.setState({
openDeleteDialog : bool
})
}
setFree = (bool) =>{
this.setState({
formData : {
...this.state.formData,
is_free: bool,
price : 0
},
disabled_price : bool
})
}
render() {
//add mock data for tag option, change this if api for tag is complete
const children = [];
for (let i = 10; i < 36; i++) {
children.push(<Option key={i.toString(36) + i}>{i.toString(36) + i}</Option>);
}
const { previewVisible, previewImage, fileList } = this.state;
const uploadButton = (
<div>
<Icon type="plus" />
<div className="ant-upload-text">Upload</div>
</div>
);
const actions = [
<FlatButton
label="Cancel"
primary={true}
style={{marginRight: 10}}
onClick={this.handleClose}
/>,
<RaisedButton
label={this.props.match.params.id ? "Edit" : "Publish"}
primary={true}
disabled={this.itemStore.isLoading}
onClick={this.props.match.params.id ? this.editData : this.postData}
/>,
];
const actionsDelete = [
<FlatButton
label="Cancel"
primary={true}
style={{marginRight: 10}}
onClick={()=>this.handleWarningDialog(false)}
/>,
<RaisedButton
label={"Delete"}
primary={true}
disabled={this.itemStore.isLoading}
onClick={this.deleteData}
/>,
];
const actionsBack = [
<FlatButton
label="No"
primary={true}
style={{marginRight: 10}}
onClick={this.handleBackClose}
/>,
<RaisedButton
label="Yes"
primary={true}
onClick={() => this.props.history.goBack()}
/>,
];
const actionsEmpty = [
<RaisedButton
label="Yes"
primary={true}
onClick={this.handleEmptyClose}
/>,
];
const wrapperText = key => ele => React.cloneElement(ele, {
value: this.state.formData[key],
onChange: (e) => {
let data = e.target.value
this.setState({
formData: {
...this.state.formData,
[key]: data
}
});
}
});
const wrapperSelect = key => ele => React.cloneElement(ele, {
value: this.state.formData[key],
onChange: (e, k, v) => {
this.setState({
formData: {
...this.state.formData,
[key]: [e],
}
}, () => {
if(e == 'b0819754-fb35-4e52-be67-eb76ca80c5a4'){
this.setState({
visible:true
})
}
else{
this.contentManagerStore.clearItems();
this.setState({
visible:false
})
}
});
}
});
const wrapperSelectType = key => ele => React.cloneElement(ele, {
value: this.state.formData[key],
onChange: (e, k, v) => {
this.setState({
formData: {
...this.state.formData,
[key]: e,
}
}, () => {
console.log('value',this.state.formData[key])
console.log('value2',e)
console.log("Key",key)
});
}
});
const wrapperSelectANT = key => ele => React.cloneElement(ele, {
value: this.state.formData.additional_data[key],
// errorText: this.state.errorText[key],
onChange: (v) => {
this.setState({
formData: {
...this.state.formData,
additional_data:{
[key] : v
}
}
}, () => {
console.log("value",this.state.formData.additional_data[key]);
console.log("value2",v);
console.log("key",key);
});
}
});
const wrapperTree = key => ele => React.cloneElement(ele, {
value: this.state.formData.additional_data[key],
// errorText: this.state.errorText[key],
onChange: (v) => {
this.setState({
formData: {
...this.state.formData,
additional_data:{
[key] : v
}
}
}, () => {
console.log("value",this.state.formData.additional_data[key]);
this.contentManagerStore.itemChange(v);
});
}
});
return (
<div style={{marginTop: 35}}>
<div className="row">
<div className="col s12">
<Card className="animated fadeIn cardLite" style={{marginLeft: 12, marginRight: 12}}>
<Toolbar className="toolbarCard" style={{backgroundColor: '#fff'}}>
<ToolbarGroup>
<IconButton
iconClassName="material-icons"
tooltip="Back"
style={{marginLeft: '-10px'}}
onClick={this.handleBackOpen}
>
arrow_back
</IconButton>
<ToolbarTitle style={{fontSize: 14, fontWeight: 500, color: '#32325d'}} text={this.props.match.params.id ? 'Edit Content' : 'Create Content'}/>
</ToolbarGroup>
<ToolbarGroup>
{!(this.state.mode == 'create') ? <RaisedButton onClick={()=>this.handleWarningDialog(true)} icon={<DeleteIcon/>} label="Delete" primary={true} style={{marginRight : '1px'}}/> : ''}
{/*!(this.state.mode == 'update') ? <RaisedButton icon={<SaveIcon/>} label="Save as draft" primary={true} style={{marginRight : '1px'}}/> : ''*/}
</ToolbarGroup>
</Toolbar>
</Card>
</div>
</div>
<div className={"row"}>
<div className={"col s12"}>
<div className="row">
<div className={"col s9"}>
<Card className="animated fadeIn cardLite">
<FroalaEditor
model={this.state.text}
config={this.state.config}
onModelChange={this.handleModelChange}
onManualControllerReady={(initControls) => {
console.log(initControls, 'initControls initControls');
initControls.initialize();
this.editor = initControls.getEditor();
this.editor().on('froalaEditor.image.beforeUpload', (e, editor, files) => {
if (files.length) {
let name = files[0].name;
this.props.appstate.http.upload(files[0]).then(it => {
editor.image.insert(this.http.appendImagePath(it.path), name, null, editor.image.get());
// console.log(it);
});
// let reader = new FileReader();
// reader.onload = (e) => {
// let result = e.target.result;
// editor.image.insert(result, null, null, editor.image.get());
// };
// reader.readAsDataURL(files[0]);
}
return false;
});
this.editor().on('froalaEditor.file.beforeUpload', (e, editor, files) => {
// console.log(e, editor, files, 'blah blah blah')
if (files.length) {
let name = files[0].name;
this.props.appstate.http.upload(files[0]).then(it => {
editor.file.insert(this.http.appendImagePath(it.path), name, null);
// console.log(it);
});
}
return false;
});
this.editor().on('froalaEditor.video.beforeUpload', (e, editor, files) => {
// console.log(e, editor, files, 'blah blah blah')
if (files.length) {
let name = files[0].name;
// console.log(editor.video);
this.props.appstate.http.upload(files[0]).then(it => {
this.editor('video.insert', `<iframe controls="true" width="90%" height="100%" src="${this.http.appendImagePath(it.path)}" style="vertical-align:middle"/>`, false);
// console.log(it);
});
}
return false;
});
}}
/>
</Card>
</div>
<div className={"col s3"}>
<Affix offsetTop={85}>
<Card className="animated fadeIn cardLite">
<div style={{padding: '14px'}}>
<div className="row">
<p className="label-form">Title Content</p>
{wrapperText("title")(
<Input placeholder="E.g. Title" autosize type={"text"}/>
)}
</div>
<div className="row">
<p className="label-form">Tag</p>
{wrapperSelect("tags")(
<Select placeholder="Select a tag" style={{width: '100%',overflow: 'scroll'}}>
{this.contentManagerStore.listTags.map(c => {
return <Option key={c.id} value={c.id}>{c.name}</Option>
})}
</Select>
)}
</div>
{/*<div className="row">*/}
{/*<p className="label-form">Types</p>*/}
{/*{wrapperSelectType("type")(*/}
{/*<Select placeholder="Select a type" style={{width: '100%',overflow: 'scroll'}}>*/}
{/*<Option value="template1">Template Full Card</Option>*/}
{/*<Option value="template2">Template Standart List</Option>*/}
{/*/!*<Option value="template3">Template Surf & turf</Option>*!/*/}
{/*</Select>*/}
{/*)}*/}
{/*</div>*/}
{this.state.visible == true ? (
<div className="row">
<p className="label-form">Items</p>
{/*{wrapperSelectANT("items")(<Select*/}
{/*mode="multiple"*/}
{/*style={{ width: '100%' }}*/}
{/*placeholder="E.g Dori,Cumi,Ikan"*/}
{/*optionFilterProp="children"*/}
{/*filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}*/}
{/*>*/}
{/*{this.contentManagerStore.listItems.map(data=>{*/}
{/*return <Option key={data.id} value={data.id}>{data.name}</Option>*/}
{/*})}*/}
{/*</Select>)}*/}
{wrapperTree("items")(
<TreeSelect
showSearch
style={{ width: '100%' }}
value={this.state.value}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="select a product"
allowClear
multiple
treeDefaultExpandAll
filterTreeNode={(input,treeNode)=>{
// return lowerCase(treeNode.props.title).includes(lowerCase(input));
return true;
}}
onSearch={async (input)=>{
await this.contentManagerStore.getItem(input);
}}
onSelect={(value)=>{
this.contentManagerStore.addSelectedItem(value);
}}
// treeData={[{value : 'cou',title:'cooo',selectable: false,children :[{value :'yeyeye',title :'KOKOKO'}]},
// {value : 'skemberlu',title:'anehya',selectable: false,children :[{value :'ngerti',title :'nice'}]}]}
treeData={this.contentManagerStore.itemSearch.slice().map((it,index)=>{
return {
value : it.user_store.id+index,
title : it.user_store.name,
selectable : false,
children : [{
value : it.id,
title : it.name
}]
}
})}
>
{/*<TreeNode value="parent 1" title="parent 1" key="0-1" disableCheckbox>*/}
{/*<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">*/}
{/*<TreeNode value="leaf1" title="my leaf" key="random" />*/}
{/*<TreeNode value="leaf2" title="your leaf" key="random1" />*/}
{/*</TreeNode>*/}
{/*<TreeNode value="parent 1-1" title="parent 1-1" key="random2">*/}
{/*<TreeNode value="sss" title={<b style={{ color: '#08c' }}>sss</b>} key="random3" />*/}
{/*<TreeNode value="leaf2" title="your leaf" key="random1" />*/}
{/*</TreeNode>*/}
{/*</TreeNode>*/}
</TreeSelect>
)}
</div>
) : ('')}
{this.props.match.params.id ? (<ButtonAntd type={'primary'} style={{width: '100%', marginTop: 25}} onClick={this.handleOpen} icon={'save'}>Save</ButtonAntd>) : (<ButtonAntd type={'primary'} style={{width: '100%', marginTop: 25}} onClick={this.handleOpen} icon={'upload'}>Publish</ButtonAntd>)}
</div>
</Card>
</Affix>
</div>
</div>
<Dialog
title="Warning"
actions={actions}
modal={true}
open={this.state.openedDialog}
onRequestClose={() => this.handleClose()}
>
Make sure all of your data is correct before submitting.
</Dialog>
<Dialog
title="Warning"
actions={actionsBack}
modal={true}
contentStyle={{width: 350}}
open={this.state.openedDialogBack}
onRequestClose={() => this.handleBackClose()}
>
Are you sure you wanna go back ?
</Dialog>
<Dialog
title="Warning"
actions={actionsDelete}
modal={true}
open={this.state.openDeleteDialog}
onRequestClose={() => this.handleWarningDialog(false)}
>
Are you sure want to delete this item?
</Dialog>
<Dialog
title="Warning"
actions={actionsEmpty}
modal={true}
contentStyle={{width: 350}}
open={this.state.openedDialogEmpty}
onRequestClose={() => this.handleEmptyClose()}
>
All data cannot be empty !
</Dialog>
</div>
</div>
</div>
)
}
}