You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
391 lines
12 KiB
391 lines
12 KiB
import React, { Component } from 'react'; |
|
import BootstrapTable from 'react-bootstrap-table-next'; |
|
import ToolkitProvider, { Search, CSVExport } from 'react-bootstrap-table2-toolkit'; |
|
import paginationFactory from 'react-bootstrap-table2-paginator'; |
|
import cellEditFactory from 'react-bootstrap-table2-editor'; |
|
import { Badge, Card, CardBody, CardHeader, Col, Row, Table, Button, |
|
Modal, ModalHeader, ModalBody, ModalFooter, |
|
Form, FormGroup, Label, Input, FormText |
|
} from 'reactstrap'; |
|
import { Icon, InlineIcon } from '@iconify/react'; |
|
import createOutline from '@iconify/icons-ion/create-outline'; |
|
import archiveOutline from '@iconify/icons-ion/archive-outline'; |
|
import addCircleOutline from '@iconify/icons-ion/add-circle-outline'; |
|
import { AppSwitch } from '@coreui/react'; |
|
import { UncontrolledTooltip } from 'reactstrap'; |
|
import './DataTable.css'; |
|
import SweetAlert from 'react-bootstrap-sweetalert'; |
|
import moment from "moment" |
|
|
|
import { resetWarningCache } from 'prop-types'; |
|
|
|
const dataColumns = [{ |
|
dataField: 'id', |
|
text: 'Id' |
|
}]; |
|
|
|
const { SearchBar } = Search; |
|
const { ExportCSVButton } = CSVExport; |
|
|
|
class DataTable extends Component { |
|
constructor(props) { |
|
const {columns} = props |
|
const val = columns.reduce((obj, item) => (obj[item.dataField] = item.state, obj) ,{}); |
|
super(props) |
|
this.state = { |
|
columns: [], |
|
data: [], |
|
selectRow: { |
|
mode: 'checkbox', |
|
clickToSelect: true, |
|
clickToEdit: false, |
|
bgColor: '#e4e5e6', |
|
onSelect: (row, isSelect, rowIndex, e) => this.onSelectRowTable({row, isSelect, e, rowIndex}), |
|
onSelectAll: (isSelect, rows, e) => this.onSelectRowTable({row: rows, isSelect, e}), |
|
}, |
|
editCellMode: false, |
|
onSelectAllMode: false, |
|
selectedRows: [], |
|
alert: false, |
|
alertWarning: false, |
|
successAlert: false, |
|
dangerAlert: false, |
|
messageAlert: "", |
|
openDialog : false, |
|
editData : false, |
|
... val |
|
} |
|
this.mapTableInit = this.mapTableInit.bind(this); |
|
} |
|
|
|
getDataTable = () => { |
|
fetch(this.props.urlParamGet, { |
|
method: 'POST', |
|
header: JSON.stringify({ |
|
'Content-Type': 'application/json' |
|
}) |
|
}).then((response) => response.json()) |
|
.then((responseJson) => { |
|
if(responseJson.code_message === "Success"){ |
|
let dataArray = [] |
|
|
|
for(let i = 0; i < responseJson.data.length; i++){ |
|
dataArray.push(responseJson.data[i]); |
|
} |
|
|
|
this.mapTableInit(dataArray) |
|
|
|
}else{ |
|
|
|
console.log("gagal login"); |
|
} |
|
}).catch((error) => { |
|
|
|
}); |
|
} |
|
|
|
|
|
componentDidMount() { |
|
this.getDataTable(); |
|
} |
|
|
|
mapTableInit(data) { |
|
|
|
let columns = []; |
|
if (data.length > 0) { |
|
for (let key in data[0]) { |
|
columns.push({ |
|
dataField: key, |
|
text: key, |
|
sort: true |
|
}) |
|
} |
|
} |
|
|
|
this.setState({ |
|
columns: data.length !== 0 ? columns:dataColumns, |
|
data: data |
|
}) |
|
} |
|
|
|
|
|
onSelectRowTable = ({row, isSelect, e}) => { |
|
const {selectedRows} = this.state |
|
if(typeof row === "object"){ |
|
if(isSelect){ |
|
this.setState({selectedRows: [...selectedRows, row]}) |
|
} else { |
|
const idx = selectedRows.indexOf(row) |
|
selectedRows.splice(idx, 1) |
|
this.setState({selectedRows}) |
|
} |
|
|
|
} else { |
|
console.log("type array") |
|
this.setState({selectedRows: row}) |
|
} |
|
} |
|
|
|
openDialog = () => this.setState({openDialog: true}) |
|
|
|
closeDialog = () => this.setState({openDialog: false}) |
|
|
|
saveDialog = async () => { |
|
const {editData} = this.state |
|
const {columns, urlParamInsert, urlParamUpdate} = this.props |
|
|
|
const urlParam = editData ? urlParamUpdate:urlParamInsert |
|
|
|
const val = columns.reduce((obj, item) => (obj[item.dataField] = item.state, obj) ,{}); |
|
|
|
const obj = columns.reduce((obj, item) => Object.assign(obj, { |
|
[item.dataField]: item.dataField === "last_updated" || item.dataField === "created_time" || item.dataField === "modified_time" |
|
? moment().format("YYYY-MM-DD HH:mm:ssZ"): this.state[item.dataField] |
|
}), {}); |
|
|
|
const param = { |
|
method: 'POST', |
|
header: JSON.stringify({'Content-Type': 'application/json'}), |
|
body: JSON.stringify(obj) |
|
} |
|
this.setState({selectedRows: []}) |
|
try { |
|
const result = await fetch(urlParam, param).then(response => response.json()).then(res => res) |
|
if(result.data){ |
|
this.getDataTable(); |
|
this.setState({openDialog: false, alert: true, messageAlert: result.code_message, successAlert: true, dangerAlert: false, ...val}) |
|
} else { |
|
this.setState({openDialog: false, alert: true, messageAlert: result.code_message, successAlert: false, dangerAlert: true, ...val}) |
|
} |
|
} catch { |
|
this.setState({openDialog: false, alert: true, messageAlert: "Opss! looks like something wrong", successAlert: false, dangerAlert: true, ...val}) |
|
} |
|
|
|
} |
|
|
|
dialogContent = () => { |
|
const {editData, openDialog} = this.state |
|
const {columns} = this.props |
|
return ( |
|
<div> |
|
<Modal isOpen={openDialog} toggle={this.closeDialog} > |
|
<ModalHeader toggle={this.closeDialog}>{editData ? "Update data":"Add new"} {this.props.title}</ModalHeader> |
|
<ModalBody> |
|
{columns.map((res, idx) => { |
|
if(res.showInput){ |
|
return ( |
|
<FormGroup key={idx}> |
|
<Label for="exampleEmail">{res.alias}</Label> |
|
<Input value={this.state[res.dataField]} onChange={(e) => this.setState({[res.dataField]: e.target.value})} type={res.type} /> |
|
</FormGroup> |
|
) |
|
} |
|
|
|
})} |
|
</ModalBody> |
|
<ModalFooter> |
|
|
|
<Button color="secondary" onClick={this.closeDialog}>Cancel</Button> |
|
<Button color="primary" onClick={this.saveDialog}>Save</Button>{' '} |
|
</ModalFooter> |
|
</Modal> |
|
</div> |
|
) |
|
} |
|
|
|
getDataUpdate = () => { |
|
const {selectedRows} = this.state |
|
this.setState({ |
|
...selectedRows[0], |
|
openDialog: true, |
|
editData: true |
|
}) |
|
} |
|
|
|
updateFunction = async (oldValue, newValue, row, column) => { |
|
let {editCellMode} = this.state |
|
console.log('editCellMode', editCellMode); |
|
console.log(row) |
|
|
|
const param = { |
|
method: 'POST', |
|
header: JSON.stringify({'Content-Type': 'application/json'}), |
|
body: JSON.stringify(row) |
|
} |
|
|
|
const result = await fetch(this.props.urlParamUpdate, param).then(response => response.json()).then(res => res) |
|
if(result.data){ |
|
this.getDataTable() |
|
this.setState({alert: true, successAlert: true, dangerAlert: false, messageAlert: result.code_message, editCellMode: false}) |
|
} else { |
|
this.setState({alert: true, successAlert: false, dangerAlert: true, messageAlert: result.code_message }) |
|
} |
|
} |
|
|
|
handleDelete = data => { |
|
|
|
} |
|
|
|
deleteFunction = async param => { |
|
const {selectedRows} = this.state |
|
console.log("row selected",selectedRows) |
|
if(param === "delete") { |
|
|
|
const {columns} = this.props |
|
const val = columns.reduce((obj, item) => (obj[item.dataField] = item.state, obj) ,{}); |
|
const param = { |
|
method: 'POST', |
|
header: JSON.stringify({'Content-Type': 'application/json'}), |
|
body: JSON.stringify(selectedRows) |
|
} |
|
|
|
try { |
|
const result = await fetch(this.props.urlParamDelete, param).then(response => response.json()).then(res => res) |
|
if(result.data){ |
|
this.getDataTable(); |
|
this.setState({alert: true, alertWarning: false, messageAlert: result.code_message, successAlert: true, dangerAlert: false, ...val}) |
|
} else { |
|
this.setState({alert: true, alertWarning: false, messageAlert: result.code_message, successAlert: false, dangerAlert: true, ...val}) |
|
} |
|
} catch { |
|
this.setState({alert: true, messageAlert: "Opss! looks like something wrong", successAlert: false, dangerAlert: true}) |
|
} |
|
} else { |
|
this.setState({alertWarning: false}) |
|
} |
|
|
|
|
|
} |
|
|
|
allDeleteFunction = () => { |
|
console.log() |
|
} |
|
|
|
render() { |
|
const { columns, data, selectedRows, selectRow, editCellMode, alert, messageAlert, |
|
alertWarning, deleteData, successAlert, dangerAlert } = this.state; |
|
return ( |
|
|
|
<div className="animated fadeIn"> |
|
<SweetAlert show={alert} success={successAlert} danger={dangerAlert} title={messageAlert} onConfirm={() => this.setState({alert: false, successAlert: false, dangerAlert: false})}> |
|
{messageAlert} |
|
</SweetAlert> |
|
|
|
<SweetAlert |
|
show={alertWarning} |
|
warning |
|
showCancel |
|
confirmBtnText="Yes, delete it!" |
|
confirmBtnBsStyle="danger" |
|
title="Are you sure?" |
|
onConfirm={() => this.deleteFunction("delete")} |
|
onCancel={() => this.deleteFunction("cancel")} |
|
focusCancelBtn |
|
> |
|
This {this.props.title} will be deleted |
|
</SweetAlert> |
|
|
|
<Row> |
|
<Col xl={12}> |
|
<Card> |
|
<CardHeader> |
|
<Row> |
|
<Col xl={6} xs={6}> |
|
<i className="fa fa-align-justify"></i>Master { this.props.title !== undefined ? this.props.title : 'DataTable' } |
|
</Col> |
|
<Col xl={6} xs={6}> |
|
<div className="add-button-container"> |
|
<Button color="primary" size="sm" outline onClick={this.openDialog}> |
|
<Icon icon={addCircleOutline} width={15} height={15} /> Add New Data |
|
</Button> |
|
|
|
{this.dialogContent()} |
|
</div> |
|
</Col> |
|
</Row> |
|
</CardHeader> |
|
<CardBody> |
|
{data.length === 0 ? ( |
|
<div>No result found</div> |
|
):( |
|
<div> |
|
<ToolkitProvider |
|
keyField={"id"} |
|
data={ data } |
|
columns={ columns } |
|
search |
|
exportCSV |
|
> |
|
{ |
|
props => ( |
|
<div> |
|
<Row> |
|
<Col xl={6} xs={6}> |
|
<div className="search-bar-wrapper"> |
|
<SearchBar { ...props.searchProps } /> |
|
</div> |
|
</Col> |
|
<Col xl={6} xs={6}> |
|
<div className="table-option-button-group pull-right"> |
|
<Row> |
|
|
|
{/* <div style={{paddingRight: 5}} className="switch-button-upper clearfix"> |
|
<small><b>Edit</b></small><br /> |
|
|
|
<AppSwitch className={'float-right'} variant={'pill'} label color={'success'} size={'sm'} onChange={() => this.toggleEditCell()} defaultChecked={editCellMode} /> |
|
</div> */} |
|
|
|
<div className="clearfix"> |
|
{selectedRows.length === 1 && <Button style={{marginRight: 5}} onClick={this.getDataUpdate} size="sm" outline color="success"><i className="cil-pencil"></i></Button>} |
|
{selectedRows.length > 0 && <Button onClick={() => this.setState({alertWarning: true})} size="sm" outline color="danger"><i className="cil-trash"></i></Button>} |
|
|
|
<ExportCSVButton { ...props.csvProps }> |
|
<Button color="success" size="sm" outline id="exportCSVTooltip"> |
|
<Icon icon={archiveOutline} width={20} height={20} /> |
|
</Button> |
|
</ExportCSVButton> |
|
<UncontrolledTooltip placement="top" target="exportCSVTooltip"> |
|
Export CSV |
|
</UncontrolledTooltip> |
|
</div> |
|
</Row> |
|
</div> |
|
</Col> |
|
</Row> |
|
{/*<hr />*/} |
|
<div className="table-wrapper"> |
|
<BootstrapTable |
|
{ ...props.baseProps } |
|
bootstrap4 |
|
keyField={"id"} |
|
hover |
|
pagination={ paginationFactory() } |
|
noDataIndication={ 'No results found' } |
|
selectRow={ selectRow } |
|
cellEdit={ editCellMode ? cellEditFactory({ |
|
mode: 'click', |
|
blurToSave: true, |
|
timeToCloseMessage: 2500, |
|
errorMessage: '', |
|
afterSaveCell: (oldValue, newValue, row, column) => this.updateFunction(oldValue, newValue, row, column), |
|
}) : false } |
|
/> |
|
</div> |
|
</div> |
|
) |
|
} |
|
</ToolkitProvider> |
|
</div> |
|
|
|
)} |
|
|
|
</CardBody> |
|
</Card> |
|
</Col> |
|
</Row> |
|
</div> |
|
) |
|
} |
|
} |
|
|
|
export default DataTable; |