The below code contains the data that will be displayed in react table format. Here Sometimes I am getting intermittent issue while saving the data. The save button will be enabled only once we do any update on table, that is after addition, update(edit), delete and disable otherwise.
But sometimes it is getting disabled, even after updation.
import React, { useState, useEffect, forwardRef } from 'react';
import PropTypes from 'prop-types';
import withContext from 'shared/HOCs/withContext';
import Select from 'app/shared/components/Select/Select';
import { getShops, getShopConfiguration, updateShopConfiguration } from './api';
import MaterialTable from "material-table";
import Check from '@material-ui/icons/Check';
import Clear from '@material-ui/icons/Clear';
import Edit from '@material-ui/icons/Edit';
import ViewColumn from '@material-ui/icons/ViewColumn';
import AddBox from '@material-ui/icons/AddBox';
import FilterList from '@material-ui/icons/FilterList';
import FirstPage from '@material-ui/icons/FirstPage';
import LastPage from '@material-ui/icons/LastPage';
import Search from '@material-ui/icons/Search';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';
import Remove from '@material-ui/icons/Remove';
import DeleteOutline from '@material-ui/icons/DeleteOutline';
import Button from '@material-ui/core/Button';
const FeatureFlags = (props) => {
const [allShops, setAllShops] = useState([]);
const [data, setData] = useState([]);
const [configLabel, setConfigLabel] = useState("Default Configuration");
const [selectedShop, setSelectedShop] = useState({
value: "All",
label: "All",
});
const [isSaveEnabled, setIsSaveEnabled] = useState(true);
const [actionPerformed, setActionPerformed] = useState(false);
const columns = [
{
title: "Type",
field: 'flag'.trim(),
editable: 'onAdd',
validate: rowData => {
if(rowData.flag===undefined || /^ *$/.test(rowData.flag)){
return 'Required'
}
return true
}}, {
title: "Value",
field: "value",
initialEditValue: 'false',
lookup: {
true: 'true',
false: 'false'
}
},
{
title: "State",
field: "shopId",
editable: 'never',
initialEditValue: 'All',
sorting: false
}
];
/* eslint-disable react/display-name */
const tableIcons = {
Add: forwardRef((props, ref) => selectedShop.value === 'All' && <AddBox onClick={() => setIsSaveEnabled(false)} {...props} ref={ref} />),
Check: forwardRef((props, ref) => <Check {...props} onClick={() => setIsSaveEnabled(true)} ref={ref} />),
Clear: forwardRef((props, ref) => <Clear {...props} onClick={() => setIsSaveEnabled(true)} ref={ref} />),
Edit: forwardRef((props, ref) => <Edit {...props} onClick={() => setIsSaveEnabled(false)} ref={ref} />),
ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />),
Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
Delete: forwardRef((props, ref) => <DeleteOutline {...props} onClick={() => setIsSaveEnabled(false)} ref={ref} />),
};
/* eslint-disable react/display-name */
useEffect(() => {
if (allShops.length === 0) {
getShopsList();
}
}, [allShops]);
useEffect(() => {
getConfiguration(selectedShop);
}, [selectedShop])
const getShopsList = async () => {
const response = await (await getShops(props.context)).data;
setAllShops(response);
};
const getConfiguration = async (shop) => {
let currentShop
if (shop) {
currentShop = shop.value
}
const response = await (await getShopConfiguration(props.context, currentShop)).data;
console.log('response :>> ', response);
setData(response);
}
const handleChange = (shop) => {
setSelectedShop(shop);
if (shop === null) {
setConfigLabel("Default Configuration");
setSelectedShop({ value: "All", label: "All" });
} else {
setConfigLabel("Shop " + shop.value + " Configuration");
}
};
const updateTableData = (newData, oldData) => {
newData.shopId = selectedShop.value
setActionPerformed(true)
// eslint-disable-next-line no-unused-vars
return new Promise((resolve, reject) => {
setTimeout(() => {
const dataUpdate = [...data];
const index = oldData.tableData.id;
dataUpdate[index] = newData;
setData([...dataUpdate]);
resolve();
}, 300)
})
}
const addRowToTable = (newData) => {
setActionPerformed(true)
const checkData = data.some( x => x.flag === newData.flag);
if(checkData){
return new Promise((resolve) => {
setTimeout(() => {
setData([...data]);
resolve();
}, 300);
})
}else{
// eslint-disable-next-line no-unused-vars
return new Promise((resolve, reject) => {
setTimeout(() => {
setData([...data, newData]);
resolve();
}, 300);
})
}
}
const deleteRow = (oldData) => {
setActionPerformed(true)
// eslint-disable-next-line no-unused-vars
return new Promise((resolve, reject) => {
setTimeout(() => {
const dataDelete = [...data];
const index = oldData.tableData.id;
dataDelete.splice(index, 1);
setData([...dataDelete]);
resolve();
}, 300);
})
}
const saveConfig = async () => {
var currentShop = selectedShop.value
var updatedData
if (currentShop !== 'All') {
updatedData = data.filter( item => item.shopId !== 'All')
} else {
updatedData = data
}
if (updatedData.length > 0 && actionPerformed) {
const response = await updateShopConfiguration(props.context, currentShop, updatedData);
console.log(`response ===`, response)
if (response === 'error') {
getConfiguration(selectedShop);
}
}
setActionPerformed(false)
}
console.log('isSaveEnabled :>> ', isSaveEnabled, actionPerformed);
return (
<div className="page page-dashboard">
<header>
<h1>Feature Flags</h1>
</header>
<div className="content no-padding">
<div className="advanced-filter">
<div className="filters active">
<div className="filter">
<label htmlFor={'shop'}>Select Shop</label>
<Select
id="shop"
defaultValue={{ label: "All", value: "All" }}
placeholder={"Select Shop"}
options={allShops}
value={selectedShop}
onChange={handleChange}
isClearable
/>
</div>
</div>
</div>
{data.length > 0 && (
<div className="list overflow-list">
<MaterialTable
icons={tableIcons}
options={{
paging: false,
addRowPosition: 'first'
}}
columns={columns}
data={data}
editable={{
isDeleteHidden: (row)=>row.shopId!=selectedShop.value,
onRowUpdate: (newData, oldData) => updateTableData(newData, oldData),
onRowAdd: (newData) =>addRowToTable(newData),
onRowDelete: ( oldData ) => deleteRow(oldData)
}}
title={configLabel}
/>
</div>
)}
{actionPerformed && <div style={{marginTop:'50px'}}>
<Button variant="contained" color="primary" disabled={ !isSaveEnabled } onClick = {saveConfig} >Save Changes</Button>
</div>}
</div>
</div>
);
};
FeatureFlags.propTypes = {
context: PropTypes.object.isRequired,
};
export default withContext(FeatureFlags);
Any leads would be appreciated.