// SPDX-License-Identifier: AGPL-3.0
import * as React from 'react';
-import { Grid, Paper, Toolbar } from '@material-ui/core';
+import { Grid, Paper, Toolbar, StyleRulesCallback, withStyles, Theme, WithStyles, TablePagination, Table, IconButton } from '@material-ui/core';
+import MoreVertIcon from "@material-ui/icons/MoreVert";
import ContextMenu, { ContextMenuActionGroup, ContextMenuAction } from "../../components/context-menu/context-menu";
import ColumnSelector from "../../components/column-selector/column-selector";
-import DataTable from "../../components/data-table/data-table";
+import DataTable, { DataColumns } from "../../components/data-table/data-table";
import { mockAnchorFromMouseEvent } from "../../components/popover/helpers";
-import { DataColumn, toggleSortDirection } from "../../components/data-table/data-column";
+import { DataColumn } from "../../components/data-table/data-column";
import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
+import SearchInput from '../search-input/search-input';
interface DataExplorerProps<T> {
items: T[];
- columns: Array<DataColumn<T>>;
+ columns: DataColumns<T>;
contextActions: ContextMenuActionGroup[];
+ searchValue: string;
+ rowsPerPage: number;
+ page: number;
+ onSearch: (value: string) => void;
onRowClick: (item: T) => void;
onColumnToggle: (column: DataColumn<T>) => void;
onContextAction: (action: ContextMenuAction, item: T) => void;
onSortToggle: (column: DataColumn<T>) => void;
onFiltersChange: (filters: DataTableFilterItem[], column: DataColumn<T>) => void;
+ onChangePage: (page: number) => void;
+ onChangeRowsPerPage: (rowsPerPage: number) => void;
}
interface DataExplorerState<T> {
};
}
-class DataExplorer<T> extends React.Component<DataExplorerProps<T>, DataExplorerState<T>> {
+class DataExplorer<T> extends React.Component<DataExplorerProps<T> & WithStyles<CssRules>, DataExplorerState<T>> {
state: DataExplorerState<T> = {
contextMenu: {}
};
actions={this.props.contextActions}
onActionClick={this.callAction}
onClose={this.closeContextMenu} />
- <Toolbar>
- <Grid container justify="flex-end">
- <ColumnSelector
- columns={this.props.columns}
- onColumnToggle={this.props.onColumnToggle} />
- </Grid>
+ <Toolbar className={this.props.classes.toolbar}>
+ {this.props.items.length > 0 &&
+ <Grid container justify="space-between" wrap="nowrap" alignItems="center">
+ <div className={this.props.classes.searchBox}>
+ <SearchInput
+ value={this.props.searchValue}
+ onSearch={this.props.onSearch} />
+ </div>
+ <ColumnSelector
+ columns={this.props.columns}
+ onColumnToggle={this.props.onColumnToggle} />
+ </Grid>}
+
</Toolbar>
<DataTable
- columns={this.props.columns}
+ columns={[
+ ...this.props.columns,
+ this.contextMenuColumn]}
items={this.props.items}
onRowClick={(_, item: T) => this.props.onRowClick(item)}
onRowContextMenu={this.openContextMenu}
onFiltersChange={this.props.onFiltersChange}
onSortToggle={this.props.onSortToggle} />
- <Toolbar />
+ <Toolbar>
+ {this.props.items.length > 0 &&
+ <Grid container justify="flex-end">
+ <TablePagination
+ count={this.props.items.length}
+ rowsPerPage={this.props.rowsPerPage}
+ page={this.props.page}
+ onChangePage={this.changePage}
+ onChangeRowsPerPage={this.changeRowsPerPage}
+ component="div"
+ />
+ </Grid>}
+ </Toolbar>
</Paper>;
}
}
}
+ changePage = (event: React.MouseEvent<HTMLButtonElement> | null, page: number) => {
+ this.props.onChangePage(page);
+ }
+
+ changeRowsPerPage: React.ChangeEventHandler<HTMLTextAreaElement | HTMLInputElement> = (event) => {
+ this.props.onChangeRowsPerPage(parseInt(event.target.value, 10));
+ }
+
+ renderContextMenuTrigger = (item: T) =>
+ <Grid container justify="flex-end">
+ <IconButton onClick={event => this.openContextMenuWithTrigger(event, item)}>
+ <MoreVertIcon />
+ </IconButton>
+ </Grid>
+
+ openContextMenuWithTrigger = (event: React.MouseEvent<HTMLElement>, item: T) => {
+ event.preventDefault();
+ this.setState({
+ contextMenu: {
+ anchorEl: event.currentTarget,
+ item
+ }
+ });
+ }
+
+ contextMenuColumn = {
+ name: "Actions",
+ selected: true,
+ key: "context-actions",
+ renderHeader: () => null,
+ render: this.renderContextMenuTrigger
+ };
+
}
-export default DataExplorer;
+type CssRules = "searchBox" | "toolbar";
+
+const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
+ searchBox: {
+ paddingBottom: theme.spacing.unit * 2
+ },
+ toolbar: {
+ paddingTop: theme.spacing.unit * 2
+ }
+});
+
+export default withStyles(styles)(DataExplorer);