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
3 years ago
|
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;
|