File "GeoDatatable.js"

Full path: /home/satkhirabarta/public_html/wp-content/plugins/really-simple-ssl/settings/src/Settings/GeoBlockList/GeoDatatable.js
File size: 19.84 B (19.84 KB bytes)
MIME-type: text/x-java
Charset: utf-8

Download   Open   Edit   Advanced Editor &nnbsp; Back

import {useEffect, useState, useCallback} from '@wordpress/element';
import FieldsData from "../FieldsData";
import GeoDataTableStore from "./GeoDataTableStore";
import EventLogDataTableStore from "../EventLog/EventLogDataTableStore";
import FilterData from "../FilterData";
import Flag from "../../utils/Flag/Flag";
import {__} from '@wordpress/i18n';
import useFields from "../FieldsData";
import useMenu from "../../Menu/MenuData";

/**
 * A component for displaying a geo datatable.
 *
 * @param {Object} props - The component props.
 * @param {string} props.field - The field to display.
 *
 * @returns {JSX.Element} The rendered component.
 */
const GeoDatatable = (props) => {
    const {
        CountryDataTable,
        dataLoaded,
        fetchCountryData,
        addRow,
        addMultiRow,
        removeRegion,
        removeRegionMulti,
        addRegion,
        addRegionsMulti,
        removeRow,
        removeRowMulti,
        rowCleared,
        resetRowSelection,
    } = GeoDataTableStore();

    const moduleName = 'rsssl-group-filter-firewall_list_listing';
    const [localData, setLocalData] = useState([]);
    const [searchTerm, setSearchTerm] = useState('');
    const [visualData, setVisualData] = useState([]);
    const {showSavedSettingsNotice, saveFields} = FieldsData();
    const [rowsSelected, setRowsSelected] = useState([]);
    const [columns, setColumns] = useState([]);
    const {fields, fieldAlreadyEnabled, getFieldValue, setHighLightField, getField} = useFields();
    const [currentPage, setCurrentPage] = useState(1);
    const [rowsPerPage, setRowsPerPage] = useState(10);
    const {setSelectedSubMenuItem} = useMenu();
    const [DataTable, setDataTable] = useState(null);
    const [theme, setTheme] = useState(null);

    useEffect( () => {
        import('react-data-table-component').then(({ default: DataTable, createTheme }) => {
            setDataTable(() => DataTable);
            setTheme(() => createTheme('really-simple-plugins', {
                divider: {
                    default: 'transparent',
                },
            }, 'light'));
        });

    }, []);

    let enabled = getFieldValue('enable_firewall');

    const handlePageChange = (page) => {
        setCurrentPage(page);
    };
    const handlePerRowsChange = (newRowsPerPage) => {
        setRowsPerPage(newRowsPerPage);
    };

    const {
        selectedFilter,
        setSelectedFilter,
        activeGroupId,
        getCurrentFilter,
        setProcessingFilter,
    } = FilterData();

    const [filter, setFilter] = useState(getCurrentFilter(moduleName));

    const buildColumn = useCallback((column) => ({
        //if the filter is set to region and the columns = status we do not want to show the column
        omit: filter === 'regions' && (column.column === 'country_name' || column.column === 'flag'),
        name: (column.column === 'action' && 'regions' === filter) ? __('Block / Allow All', 'really-simple-ssl') : column.name,
        sortable: column.sortable,
        searchable: column.searchable,
        width: column.width,
        visible: column.visible,
        column: column.column,
        selector: row => row[column.column],
    }), [filter]);
    let field = props.field;

    useEffect(() => {
        const element = document.getElementById('set_to_captcha_configuration');
        const clickListener = async event => {
            event.preventDefault();
            if (element) {
                await redirectToAddCaptcha(element);
            }
        };

        if (element) {
            element.addEventListener('click', clickListener);
        }

        return () => {
            if (element) {
                element.removeEventListener('click', clickListener);
            }
        };
    }, []);

    const redirectToAddCaptcha = async (element) => {
        // We fetch the props from the menu item
        let menuItem = getField('enabled_captcha_provider');

        // Create a new object based on the menuItem, including the new property
        let highlightingMenuItem = {
            ...menuItem,
            highlight_field_id: 'enabled_captcha_provider',
        };

        setHighLightField(highlightingMenuItem.highlight_field_id);
        let highlightField = getField(highlightingMenuItem.highlight_field_id);
        await setSelectedSubMenuItem(highlightField.menu_id);
    }

    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 => ({
                country_code: item.iso2_code,
                country_name: item.country_name
            }));
            //we loop through the ids and block them one by one
            await addMultiRow(ids).then(
                (response) => {
                    if (response.success) {
                        showSavedSettingsNotice(response.message);
                    } else {
                        showSavedSettingsNotice(response.message, 'error');
                    }
                }
            );
            await fetchCountryData(field.action, filter);
            setRowsSelected([]);
        } else {
            await addRow(code, name).then((result) => {
                showSavedSettingsNotice(result.message);
                if (result.success) {
                    fetchCountryData(field.action, filter);
                }
            });
        }
    }, [addRow, filter, localData, enabled]);

    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
            }));
            await removeRegionMulti(ids).then(
                (response) => {
                    if (response.success) {
                        showSavedSettingsNotice(response.message);
                        if (response.success) {
                            fetchCountryData(field.action, filter);
                        }
                    } else {
                        showSavedSettingsNotice(response.message, 'error');
                    }
                }
            );
            setRowsSelected([]);
        } else {
            await removeRegion(code).then((result) => {
                showSavedSettingsNotice(result.message);
                if (result.success) {
                    fetchCountryData(field.action, filter);
                }
            });
        }
    }, [removeRegion, filter]);

    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
            }));
            await addRegionsMulti(ids).then(
                (response) => {
                    if (response.success) {
                        showSavedSettingsNotice(response.message);
                    } else {
                        showSavedSettingsNotice(response.message, 'error');
                    }
                }
            );
            await fetchCountryData(field.action, filter);
            setRowsSelected([]);
        } else {
            await addRegion(code).then((result) => {
                if (result.success) {
                    showSavedSettingsNotice(result.message);
                } else {
                    showSavedSettingsNotice(result.message, 'error');
                }
            });
            await fetchCountryData(field.action, filter);
        }

    }, [addRegion, filter]);

    const allowCountryByCode = useCallback(async (code) => {
        if (Array.isArray(code)) {
            const ids = code.map(item => ({
                country_code: item.iso2_code,
                country_name: item.country_name
            }));
            //we loop through the ids and allow them one by one
            await removeRowMulti(ids).then(
                (response) => {
                    if (response.success) {
                        showSavedSettingsNotice(response.message);
                    } else {
                        showSavedSettingsNotice(response.message, 'error');
                    }
                }
            );

            setRowsSelected([]);
            await fetchCountryData(field.action, filter);
        } else {
            await removeRow(code).then((result) => {
                showSavedSettingsNotice(result.message);
            });
            await fetchCountryData(field.action, filter);
        }

    }, [removeRow, filter]);

    const ActionButton = ({onClick, children, className, disabled = false}) => (
        // <div className={`rsssl-action-buttons__inner`}>
        <button
            className={`button ${className} rsssl-action-buttons__button`}
            onClick={onClick}
            disabled={disabled}
        >
            {children}
        </button>
        // </div>
    );

    const customStyles = {
        headCells: {
            style: {
                paddingLeft: '0',
                paddingRight: '0',
            },
        },
        cells: {
            style: {
                paddingLeft: '0',
                paddingRight: '0',
            },
        },
    };

    const generateActionButtons = useCallback((code, name, region_name, showBlockButton = true, showAllowButton = true) => {
        return (<div className="rsssl-action-buttons">
            {filter === 'blocked' && (
                <ActionButton
                    onClick={() => allowCountryByCode(code)}
                    className="button-secondary">
                    {__("Allow", "really-simple-ssl")}
                </ActionButton>
            )}
            {filter === 'regions' && (
                <>
                    <ActionButton
                        onClick={() => blockRegionByCode(code, region_name)}
                        className="button-primary"
                        disabled={!showBlockButton}
                    >
                        {__("Block", "really-simple-ssl")}
                    </ActionButton>
                    <ActionButton
                        onClick={() => allowRegionByCode(code, region_name)}
                        className="button-secondary"
                        disabled={!showAllowButton}
                    >
                        {__("Allow", "really-simple-ssl")}
                    </ActionButton>
                </>
            )}
            {filter === 'countries' && (
                <ActionButton
                    onClick={() => blockCountryByCode(code, name)}
                    className="button-primary">
                    {__("Block", "really-simple-ssl")}
                </ActionButton>
            )}
        </div>)
    }, [filter]);

    const generateFlag = useCallback((flag, title) => {
        return (
            <>
                <Flag
                    countryCode={flag}
                    style={{
                        fontSize: '2em',
                    }}
                    title={title}
                    continent={(getCurrentFilter(moduleName) === 'regions')}
                />
            </>
        )
    }, [filter]);


    useEffect(() => {
        const currentFilter = getCurrentFilter(moduleName);
        if (typeof currentFilter === 'undefined') {
            setFilter('regions');
            setSelectedFilter('regions', moduleName);
        } else {
            setFilter(currentFilter);
        }
        setRowsSelected([]);
        resetRowSelection(true);
        resetRowSelection(false);
    }, [getCurrentFilter(moduleName)]);

    useEffect(() => {
        if (filter !== undefined) {
            const fetchData = async () => {
                await fetchCountryData(field.action, filter);
            }
            fetchData();
        }

    }, [filter]);

    useEffect(() => {
        if (dataLoaded && CountryDataTable.data !== undefined) {
            setLocalData(CountryDataTable.data);
        }
    }, [dataLoaded]);

    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, visualData]);

    useEffect(() => {
        let FilterColumns = field.columns.map(buildColumn);
        // Find the index of the 'action' column
        const actionIndex = FilterColumns.findIndex(column => column.column === 'action');


        // If 'filter' equals 'regions' and 'action' column exists, then do the rearrangement
        if (filter === 'regions' && actionIndex !== -1) {
            const actionColumn = FilterColumns[actionIndex];

            // Remove 'action' column from its current place
            FilterColumns.splice(actionIndex, 1);
            const emptyColumn = {
                name: '',
                selector: '',
                sortable: false,
                omit: false,
                searchable: false,
            };
            // Push 'action' column to the end of the array
            FilterColumns.push(emptyColumn, actionColumn);
        }
        setColumns(FilterColumns);
        const generatedVisualData = (localData || [])
            .filter((row) => {
                return Object.values(row).some((val) => ((val ?? '').toString().toLowerCase()).includes(searchTerm.toLowerCase()));
            }).map((row) => {
                const newRow = {...row};
                columns.forEach((column) => {
                    newRow[column.column] = row[column.column];
                });
                if (filter === 'regions') {
                    let showBlockButton = (newRow.region_count - newRow.blocked_count) > 0;
                    let showAllowButton = (newRow.blocked_count > 0);
                    newRow.action = generateActionButtons(newRow.iso2_code, newRow.country_name, newRow.region, showBlockButton, showAllowButton);
                } else if (filter === 'countries') {
                    newRow.action = generateActionButtons(newRow.iso2_code, newRow.country_name, newRow.region);
                } else {
                    newRow.action = generateActionButtons(newRow.iso2_code, newRow.status, newRow.region);
                }
                newRow.flag = generateFlag(newRow.iso2_code, newRow.country_name);
                if (newRow.status) {
                    newRow.status = __(newRow.status.charAt(0).toUpperCase() + newRow.status.slice(1), 'really-simple-ssl');
                    if ('regions' === filter) {
                        // So i all is blocked we don't want to show the count also if all are allowed we don't want to show the count
                        if (newRow.blocked_count === newRow.region_count || newRow.blocked_count === 0) {
                            newRow.status = newRow.status;

                        } else {
                            newRow.status = newRow.status + ' (' + newRow.blocked_count + '/ ' + newRow.region_count + ')';
                        }
                    }

                }
                return newRow;
            });
        setVisualData(generatedVisualData);
    }, [localData, searchTerm]);

    useEffect(() => {
        if ( rowsSelected.length === 0 ) {
            resetRowSelection
        }
    }, [rowsSelected]);

    return (
        <>
            <div className="rsssl-container">
                <div>
                    {/* reserved for left side buttons */}
                </div>
                <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">
                            {filter === 'countries' && (
                                <>
                                    <ActionButton
                                        onClick={() => blockCountryByCode(rowsSelected)} className="button-primary">
                                        {__("Block", "really-simple-ssl")}
                                    </ActionButton>
                                </>
                            )}
                            {filter === 'regions' && (
                                <>
                                    <ActionButton
                                        onClick={() => allowRegionByCode(rowsSelected)} className="button-secondary">
                                        {__("Allow", "really-simple-ssl")}
                                    </ActionButton>
                                    <ActionButton
                                        onClick={() => blockRegionByCode(rowsSelected)} className="button-primary">
                                        {__("Block", "really-simple-ssl")}
                                    </ActionButton>
                                </>
                            )}
                            {filter === 'blocked' && (
                                <ActionButton
                                    onClick={() => allowCountryByCode(rowsSelected)}>
                                    {__("Allow", "really-simple-ssl")}
                                </ActionButton>
                            )}
                        </div>
                    </div>
                </div>
            )}
            {DataTable &&
            <DataTable
                columns={columns}
                data={visualData}
                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}
                paginationPerPage={rowsPerPage}
                onChangePage={handlePageChange}
                onChangeRowsPerPage={handlePerRowsChange}
                onSelectedRowsChange={handleSelection}
                clearSelectedRows={rowCleared}
                theme="really-simple-plugins"
                customStyles={customStyles}
            >
            </DataTable> }
            {!getFieldValue('enable_firewall') && (
                <div className="rsssl-locked">
                    <div className="rsssl-locked-overlay"><span
                        className="rsssl-task-status rsssl-open">{__('Disabled', 'really-simple-ssl')}</span><span>{__('Restrict access from specific countries or continents. You can also allow only specific countries.', 'really-simple-ssl')}</span>
                    </div>
                </div>
            )}
        </>
    )
}

export default GeoDatatable;