// This file is part of MinIO Console Server // Copyright (c) 2020 MinIO, Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import React from "react"; import get from "lodash/get"; import isString from "lodash/isString"; import { LinearProgress, TablePagination, Table, TableBody, TableCell, TableHead, TableRow, Paper, Grid, Checkbox, Typography, } from "@material-ui/core"; import { createStyles, Theme, withStyles } from "@material-ui/core/styles"; import { TablePaginationActionsProps } from "@material-ui/core/TablePagination/TablePaginationActions"; import TableActionButton from "./TableActionButton"; import history from "../../../../history"; import { checkboxIcons } from "../FormComponents/common/styleLibrary"; //Interfaces for table Items interface ItemActions { type: string; onClick?(valueToSend: any): any; to?: string; sendOnlyId?: boolean; } interface IColumns { label: string; elementKey: string; sortable?: boolean; renderFunction?: (input: any) => any; globalClass?: any; } interface IPaginatorConfig { rowsPerPageOptions: number[]; colSpan: number; count: number; rowsPerPage: number; page: number; SelectProps: any; onChangePage: ( event: React.MouseEvent | null, page: number ) => void; onChangeRowsPerPage?: React.ChangeEventHandler< HTMLTextAreaElement | HTMLInputElement >; ActionsComponent?: React.ElementType; } interface TableWrapperProps { itemActions?: ItemActions[] | null; columns: IColumns[]; onSelect?: (e: React.ChangeEvent) => any; idField: string; isLoading: boolean; records: any[]; classes: any; entityName: string; selectedItems?: string[]; stickyHeader?: boolean; paginatorConfig?: IPaginatorConfig; } const borderColor = "#eaeaea"; const rowText = { fontWeight: 400, fontSize: 14, borderColor: borderColor, }; const styles = (theme: Theme) => createStyles({ dialogContainer: { padding: "12px 26px 22px", }, paper: { display: "flex", overflow: "auto", flexDirection: "column", padding: "19px 38px", minHeight: "200px", }, minTableHeader: { color: "#393939", "& tr": { "& th": { fontWeight: 700, fontSize: 14, paddingBottom: 15, borderColor: borderColor, }, }, }, rowUnselected: { ...rowText, }, rowSelected: { ...rowText, color: "#201763", }, paginatorContainer: { display: "flex", justifyContent: "flex-end", padding: "5px 38px", }, checkBoxHeader: { "&.MuiTableCell-paddingCheckbox": { paddingBottom: 9, }, }, actionsContainer: { width: 150, borderColor: borderColor, }, paginatorComponent: { borderBottom: 0, }, checkBoxRow: { borderColor: borderColor, }, loadingBox: { paddingTop: "100px", paddingBottom: "100px", }, rowElement: { userSelect: "none", "&:hover": { backgroundColor: "#ececec", }, }, rowClickable: { cursor: "pointer", }, ...checkboxIcons, }); // Function that renders Title Columns const titleColumnsMap = (columns: IColumns[]) => { return columns.map((column: IColumns, index: number) => { return ( {column.label} ); }); }; // Function that renders Rows const rowColumnsMap = ( columns: IColumns[], itemData: any, classes: any, isSelected: boolean ) => { return columns.map((column: IColumns, index: number) => { const itemElement = isString(itemData) ? itemData : get(itemData, column.elementKey, null); // If the element is just a string, we render it as it is const renderElement = column.renderFunction ? column.renderFunction(itemElement) : itemElement; // If render function is set, we send the value to the function. return ( {renderElement} ); }); }; // Function to render the action buttons const elementActions = ( actions: ItemActions[], valueToSend: any, selected: boolean, idField: string ) => { return actions.map((action: ItemActions, index: number) => { if (action.type === "view") { return null; } return ( ); }); }; // Main function to render the Table Wrapper const TableWrapper = ({ itemActions, columns, onSelect, records, isLoading, entityName, selectedItems, idField, classes, stickyHeader = false, paginatorConfig, }: TableWrapperProps) => { const findView = itemActions ? itemActions.find((el) => el.type === "view") : null; const clickAction = (rowItem: any) => { if (findView) { const valueClick = findView.sendOnlyId ? rowItem[idField] : rowItem; if (findView.to) { history.push(`${findView.to}/${valueClick}`); return; } if (findView.onClick) { findView.onClick(valueClick); } } }; return ( {isLoading && ( Loading... )} {records && !isLoading && records.length > 0 ? ( {onSelect && selectedItems && ( Select )} {titleColumnsMap(columns)} {((itemActions && itemActions.length > 1) || (itemActions && itemActions.length === 1 && itemActions[0].type !== "view")) && ( Actions )} {records.map((record: any, index: number) => { const isSelected = selectedItems ? selectedItems.includes( isString(record) ? record : record[idField] ) : false; return ( { clickAction(record); }} > {onSelect && selectedItems && ( { e.stopPropagation(); e.preventDefault(); }} checkedIcon={} icon={} /> )} {rowColumnsMap(columns, record, classes, isSelected)} {((itemActions && itemActions.length > 1) || (itemActions && itemActions.length === 1 && itemActions[0].type !== "view")) && ( {elementActions( itemActions, record, isSelected, idField )} )} ); })} ) : ( {!isLoading && {`There are no ${entityName} yet.`}} )} {paginatorConfig && ( )} ); }; export default withStyles(styles)(TableWrapper);