OwlCyberSecurity - MANAGER
Edit File: WhiteListDatatable.js
import React, { useEffect, useState, useCallback } from 'react'; import DataTable, { createTheme } from "react-data-table-component"; import FieldsData from "../FieldsData"; import WhiteListTableStore from "./WhiteListTableStore"; import FilterData from "../FilterData"; import Flag from "../../utils/Flag/Flag"; import { __ } from '@wordpress/i18n'; import useFields from "../FieldsData"; import SearchBar from "../DynamicDataTable/SearchBar"; import AddButton from "./AddButton"; import AddIpAddressModal from "../LimitLoginAttempts/AddIpAddressModal"; import TrustIpAddressModal from "./TrustIpAddressModal"; const WhiteListDatatable = (props) => { const { WhiteListTable, dataLoaded, fetchWhiteListData, processing, ipAddress, addRow, removeRow, pagination, addRegion, removeRegion, resetRow, rowCleared, } = WhiteListTableStore(); const {showSavedSettingsNotice, saveFields} = FieldsData(); const [rowsSelected, setRowsSelected] = useState([]); const [modalOpen, setModalOpen] = useState(false); const [tableHeight, setTableHeight] = useState(600); // Starting height const rowHeight = 50; // Height of each row. const moduleName = 'rsssl-group-filter-geo_block_list_white_listing'; const {fields, fieldAlreadyEnabled, getFieldValue} = useFields(); const [searchTerm, setSearchTerm] = useState(''); const [currentPage, setCurrentPage] = useState(1); const [rowsPerPage, setRowsPerPage] = useState(10); const handlePageChange = (page) => { setCurrentPage(page); }; const handlePerRowsChange = (newRowsPerPage) => { setRowsPerPage(newRowsPerPage); }; /** * Build a column configuration object. * * @param {object} column - The column object. * @param {string} column.name - The name of the column. * @param {boolean} column.sortable - Whether the column is sortable. * @param {boolean} column.searchable - Whether the column is searchable. * @param {number} column.width - The width of the column. * @param {boolean} column.visible - Whether the column is visible. * @param {string} column.column - The column identifier. * * @returns {object} The column configuration object. */ const buildColumn = useCallback((column) => ({ //if the filter is set to region and the columns = status we do not want to show the column name: column.name, sortable: column.sortable, searchable: column.searchable, width: column.width, visible: column.visible, column: column.column, selector: row => row[column.column], }), []); let field = props.field; const columns = field.columns.map(buildColumn); const searchableColumns = columns .filter(column => column.searchable) .map(column => column.column); useEffect(() => { setRowsSelected([]); }, [WhiteListTable]); useEffect(() => { fetchWhiteListData(field.action); }, [fieldAlreadyEnabled('geo_blocklist_enabled')]); let enabled = getFieldValue('geo_blocklist_enabled'); useEffect(() => { return () => { saveFields(false, false) }; }, [enabled]); const customStyles = { headCells: { style: { paddingLeft: '0', paddingRight: '0', }, }, cells: { style: { paddingLeft: '0', paddingRight: '0', }, }, }; createTheme('really-simple-plugins', { divider: { default: 'transparent', }, }, 'light'); const handleSelection = useCallback((state) => { //based on the current page and the rows per page we get the rows that are selected const {selectedCount, selectedRows, allSelected, allRowsSelected} = state; let rows = []; if (allSelected) { rows = selectedRows.slice((currentPage - 1) * rowsPerPage, currentPage * rowsPerPage); setRowsSelected(rows); } else { setRowsSelected(selectedRows); } }, [currentPage, rowsPerPage]); const allowRegionByCode = useCallback(async (code, regionName = '') => { if (Array.isArray(code)) { const ids = code.map(item => ({ iso2_code: item.iso2_code, country_name: item.country_name })); ids.forEach((id) => { removeRegion(id.iso2_code).then((result) => { showSavedSettingsNotice(result.message); }); }); setRowsSelected([]); await fetchWhiteListData(field.action); setRowsSelected([]); } else { await removeRegion(code).then((result) => { showSavedSettingsNotice(result.message); }); } }, [removeRegion]); const allowById = useCallback((id) => { //We check if the id is an array if (Array.isArray(id)) { //We get all the iso2 codes and names from the array const ids = id.map(item => ({ id: item.id, })); //we loop through the ids and allow them one by one ids.forEach((id) => { resetRow(id.id).then((result) => { showSavedSettingsNotice(result.message); }); }); setRowsSelected([]); } else { resetRow(id).then((result) => { showSavedSettingsNotice(result.message); }); } fetchWhiteListData(field.action); }, [resetRow]); const blockRegionByCode = useCallback(async (code, region = '') => { if (Array.isArray(code)) { const ids = code.map(item => ({ iso2_code: item.iso2_code, country_name: item.country_name })); ids.forEach((id) => { addRegion(id.iso2_code).then((result) => { showSavedSettingsNotice(result.message); }); }); setRowsSelected([]); await fetchWhiteListData(field.action); setRowsSelected([]); } else { await addRegion(code).then((result) => { showSavedSettingsNotice(result.message); }); } }, [addRegion]); const allowCountryByCode = useCallback(async (code) => { if (Array.isArray(code)) { const ids = code.map(item => ({ iso2_code: item.iso2_code, country_name: item.country_name })); //we loop through the ids and allow them one by one ids.forEach((id) => { removeRow(id.iso2_code).then((result) => { showSavedSettingsNotice(result.message); }); }); setRowsSelected([]); await fetchWhiteListData(field.action); } else { await removeRow(code).then((result) => { showSavedSettingsNotice(result.message); }); } }, [removeRow]); const blockCountryByCode = useCallback(async (code, name) => { if (Array.isArray(code)) { //We get all the iso2 codes and names from the array const ids = code.map(item => ({ iso2_code: item.iso2_code, country_name: item.country_name })); //we loop through the ids and block them one by one ids.forEach((id) => { addRow(id.iso2_code, id.country_name).then((result) => { showSavedSettingsNotice(result.message); }); }); setRowsSelected([]); } else { await addRow(code, name).then((result) => { showSavedSettingsNotice(result.message); }); } }, [addRow]); const data = {...WhiteListTable.data}; const generateFlag = useCallback((flag, title) => ( <> <Flag countryCode={flag} style={{ fontSize: '2em', }} title={title} /> </> ), []); const ActionButton = ({ onClick, children, className }) => ( // <div className={`rsssl-action-buttons__inner`}> <button className={`button ${className} rsssl-action-buttons__button`} onClick={onClick} disabled={processing} > {children} </button> // </div> ); const handleClose = () => { setModalOpen(false); } const handleOpen = () => { setModalOpen(true); } const generateActionButtons = useCallback((id) => { return (<div className="rsssl-action-buttons"> <ActionButton onClick={() => allowById(id)} className="button-red"> {__("Reset", "really-simple-ssl")} </ActionButton> </div>) }, [moduleName, allowById, blockRegionByCode, allowRegionByCode, blockCountryByCode, allowCountryByCode]); for (const key in data) { const dataItem = {...data[key]}; dataItem.action = generateActionButtons(dataItem.id); dataItem.flag = generateFlag(dataItem.iso2_code, dataItem.country_name); dataItem.status = __(dataItem.status = dataItem.status.charAt(0).toUpperCase() + dataItem.status.slice(1), 'really-simple-ssl'); data[key] = dataItem; } let paginationSet; paginationSet = typeof pagination !== 'undefined'; useEffect(() => { if (Object.keys(data).length === 0 ) { setTableHeight(100); // Adjust depending on your UI measurements } else { setTableHeight(rowHeight * (paginationSet ? pagination.perPage + 2 : 12)); // Adjust depending on your UI measurements } }, [paginationSet, pagination?.perPage, data]); useEffect(() => { const filteredData = Object.entries(data) .filter(([_, dataItem]) => { return Object.values(dataItem).some(val => ((val ?? '').toString().toLowerCase().includes(searchTerm.toLowerCase()))); }) .map(([key, dataItem]) => { const newItem = { ...dataItem }; newItem.action = generateActionButtons(newItem.id); newItem.flag = generateFlag(newItem.iso2_code, newItem.country_name); newItem.status = __(newItem.status = newItem.status.charAt(0).toUpperCase() + newItem.status.slice(1), 'really-simple-ssl'); return [key, newItem]; }) .reduce((obj, [key, val]) => ({ ...obj, [key]: val }), {}); }, [searchTerm, data]); return ( <> <TrustIpAddressModal isOpen={modalOpen} onRequestClose={handleClose} value={ipAddress} status={'trusted'} > </TrustIpAddressModal> <div className="rsssl-container"> {/*display the add button on left side*/} <AddButton moduleName={moduleName} handleOpen={handleOpen} processing={processing} blockedText={__("Block IP Address", "really-simple-ssl")} allowedText={__("Trust IP Address", "really-simple-ssl")} /> <div className="rsssl-search-bar"> <div className="rsssl-search-bar__inner"> <div className="rsssl-search-bar__icon"></div> <input type="text" className="rsssl-search-bar__input" placeholder={__("Search", "really-simple-ssl")} onChange={e => setSearchTerm(e.target.value)} /> </div> </div> </div> {rowsSelected.length > 0 && ( <div style={{ marginTop: '1em', marginBottom: '1em', }} > <div className={"rsssl-multiselect-datatable-form rsssl-primary"}> <div> {__("You have selected %s rows", "really-simple-ssl").replace('%s', rowsSelected.length)} </div> <div className="rsssl-action-buttons"> <> <ActionButton onClick={() => allowById(rowsSelected)} className="button-red"> {__("Reset", "really-simple-ssl")} </ActionButton> </> </div> </div> </div> )} <DataTable columns={columns} data={Object.values(data).filter((row) => { return Object.values(row).some((val) => ((val ?? '').toString().toLowerCase()).includes(searchTerm.toLowerCase())); })} dense pagination={true} paginationComponentOptions={{ rowsPerPageText: __('Rows per page:', 'really-simple-ssl'), rangeSeparatorText: __('of', 'really-simple-ssl'), noRowsPerPage: false, selectAllRowsItem: false, selectAllRowsItemText: __('All', 'really-simple-ssl'), }} noDataComponent={__("No results", "really-simple-ssl")} persistTableHead selectableRows={true} clearSelectedRows={rowCleared} paginationPerPage={rowsPerPage} onChangePage={handlePageChange} onChangeRowsPerPage={handlePerRowsChange} onSelectedRowsChange={handleSelection} theme="really-simple-plugins" customStyles={customStyles} /> {!enabled && ( <div className="rsssl-locked"> <div className="rsssl-locked-overlay"><span className="rsssl-task-status rsssl-open">{__('Disabled', 'really-simple-ssl')}</span><span>{__('Here you can add IP addresses that should never be blocked by region restrictions.', 'really-simple-ssl')}</span> </div> </div> )} </> ); } export default WhiteListDatatable;