Skip to content

Commit

Permalink
feat(fixedSearch in header, more custom toolbar options, tests): Adde…
Browse files Browse the repository at this point in the history
…d an ever-present searchbar options for the header. Added more custom toolbar hooks. + test coverage for all.
  • Loading branch information
parkerself22 committed Feb 22, 2019
1 parent 5d19848 commit 06802bc
Show file tree
Hide file tree
Showing 19 changed files with 796 additions and 163 deletions.
7 changes: 5 additions & 2 deletions examples/MuiTable.stories.tsx
Expand Up @@ -9,6 +9,7 @@ import { HooksExample } from './hooks-actions';
import { IntroExample } from './intro';

storiesOf('MUITable', module)
.addDecorator(story => <div style={{ padding: 40 }}>{story()}</div>)
.add(
'Configurable Example',
() => {
Expand Down Expand Up @@ -264,14 +265,15 @@ storiesOf('MUITable', module)
showDates: boolean('showDates', false, 'Options.toolbar'),
startDate: new Date(text('startDate', '2/1/18', 'Options.toolbar')),
endDate: new Date(text('endDate', '2/1/18', 'Options.toolbar')),
customToolbar: () =>
text('customToolbar (return value)', '', 'Options.toolbar'),
customToolbarRight: () =>
text('customToolbarRight (return value)', '', 'Options.toolbar'),
handleDateChange: isStart => value => console.log(isStart, value)
},
rows: {
rowHover: boolean('rowHover', false, 'Options.rows'),
showSummaryRow: boolean('showSummaryRow', false, 'Options.rows'),
summaryTop: boolean('summaryTop', false, 'Options.rows'),
selectBarTop: boolean('selectBarTop', true, 'Options.rows'),
selectable: boolean('selectableRows', false, 'Options.rows'),
skipDuplicates: boolean('skipDuplicates', true, 'Options.rows'),
mergeDuplicates: boolean('mergeDuplicates', false, 'Options.rows'),
Expand Down Expand Up @@ -364,6 +366,7 @@ storiesOf('MUITable', module)
sort: boolean('sort', true, 'Options.display'),
filter: boolean('filter', true, 'Options.display'),
search: boolean('search', true, 'Options.display'),
fixedSearch: boolean('fixedSearch', true, 'Options.display'),
print: boolean('print', false, 'Options.display'),
download: boolean('download', false, 'Options.display'),
viewColumns: boolean('viewColumns', true, 'Options.display'),
Expand Down
10 changes: 7 additions & 3 deletions src/components/Footer/MUITableFooter.tsx
@@ -1,6 +1,7 @@
import Table from '@material-ui/core/Table';
import React from 'react';
import { useMUITableContext } from '../MUITable';
import MUITableToolbarSelect from '../Toolbars/MUITableToolbarSelect';
import MUITablePagination from './MUITablePagination';

const MUITableFooter = () => {
Expand All @@ -13,9 +14,12 @@ const MUITableFooter = () => {
return null;
}
return (
<Table>
<MUITablePagination />
</Table>
<div style={{ position: "relative" }}>
{!options.rows.selectBarTop && <MUITableToolbarSelect />}
<Table>
<MUITablePagination />
</Table>
</div>
);
};
export default MUITableFooter;
2 changes: 1 addition & 1 deletion src/components/Footer/MUITablePaginationActions.tsx
Expand Up @@ -21,7 +21,7 @@ const PaginationActions = (props: TablePaginationActionsProps & WithStyles<typeo
const { displayRows, options } = useMUITableContext();
const textLabels = options.translations.pagination;
const { classes, onChangePage, page, rowsPerPage } = props;
const lastPage = (displayRows.length / rowsPerPage) - 1;
const lastPage = displayRows.length / rowsPerPage - 1;

const handleFirstPageButtonClick = (e: any) => {
onChangePage(e, 0);
Expand Down
4 changes: 3 additions & 1 deletion src/components/MUITable.tsx
@@ -1,3 +1,4 @@
import CssBaseline from '@material-ui/core/CssBaseline';
import React, { useContext } from 'react';
import { MUITABLE_DEF_CONTEXT } from '../constants';
import MUITableUtils from '../constants/MUITableUtils';
Expand Down Expand Up @@ -38,7 +39,7 @@ export class MUIChildTable extends React.Component<Props<any>, State<any>> {
columnFilters: props.columns.map(() => []),
selectedRows: [],
search: {
open: false,
open: options.display.fixedSearch,
text: null
},
viewColumns: props.columns.map(c => c.display === 'true'),
Expand Down Expand Up @@ -298,6 +299,7 @@ export class MUIChildTable extends React.Component<Props<any>, State<any>> {

return (
<MUITABLE_DEF_CONTEXT.Provider value={context}>
<CssBaseline />
<MUITableWrapper loading={loading} />
</MUITABLE_DEF_CONTEXT.Provider>
);
Expand Down
16 changes: 8 additions & 8 deletions src/components/MUITableWrapper.tsx
@@ -1,3 +1,4 @@
import { Grid } from '@material-ui/core';
import Paper from '@material-ui/core/Paper';
import Table from '@material-ui/core/Table';
import React from 'react';
Expand Down Expand Up @@ -39,6 +40,9 @@ const classes = {
},
paper: {
position: 'relative' as 'relative'
},
toolbarGrid: {
position: 'relative' as 'relative'
}
};

Expand All @@ -52,16 +56,12 @@ const MUITableWrapper = (props: Props) => {
const { options, selectedRows } = context;
const { title } = options;
return (
<Paper
elevation={options.display.elevation}
style={classes.paper}
>
<Paper elevation={options.display.elevation} style={classes.paper}>
<MUITableLoader loading={loading} />
{selectedRows.length > 0 ? (
<MUITableToolbarSelect />
) : (
<Grid container spacing={0} style={classes.toolbarGrid}>
<MUITableToolbar context={context} />
)}
{options.rows.selectBarTop && <MUITableToolbarSelect />}
</Grid>
<MUITableFilterList />
<div
data-testid="responsive-style-div"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Summary/SummaryRow.tsx
Expand Up @@ -136,7 +136,7 @@ const SummaryRow = (props: WithStyles<typeof styles>) => {
{summaryRow.map((cell, index) => {
if (cell.visible.column.display === 'true' && viewColumns[index] !== false) {
if (index === 0 && !options.rows.selectable && cell.visible.value === null) {
return <MUISummaryTitle classes={classes} key={"0"}/>;
return <MUISummaryTitle classes={classes} key={'0'} />;
}
return (
<MUISummaryCell
Expand Down
9 changes: 5 additions & 4 deletions src/components/Toolbars/MUITableDatePicker.tsx
Expand Up @@ -18,14 +18,15 @@ const styles = (theme: Theme) =>

const MUITableDatePicker = (props: WithStyles<typeof styles>) => {
const { classes } = props;
const { options } = useMUITableContext();
const context = useMUITableContext();
const { options } = context;
const {
toolbar: {
startDate,
endDate,
showDates,
handleDateChange,
customToolbar,
customToolbarRight,
startLabel,
endLabel
}
Expand All @@ -35,7 +36,7 @@ const MUITableDatePicker = (props: WithStyles<typeof styles>) => {
if (showDates && !handleDateChange) {
throw new Error('showDates=true provided to MUITableDatePicker but no handler provided');
}
if (!showDates && !customToolbar) {
if (!showDates && !customToolbarRight) {
return null;
}

Expand All @@ -45,7 +46,7 @@ const MUITableDatePicker = (props: WithStyles<typeof styles>) => {
return (
<MuiPickersUtilsProvider utils={MomentUtils}>
<div className={classes.datePickerWrapper}>
{customToolbar ? customToolbar() : null}
{customToolbarRight ? customToolbarRight(context) : null}
{showDates && startDate && handleDateChange ? (
<InlineDatePicker
className={classnames(
Expand Down
206 changes: 206 additions & 0 deletions src/components/Toolbars/MUITableFixedSearch.tsx
@@ -0,0 +1,206 @@
import { createStyles, Theme, Typography, withStyles, WithStyles } from '@material-ui/core';
import Grid from '@material-ui/core/Grid';
import IconButton from '@material-ui/core/IconButton';
import InputAdornment from '@material-ui/core/InputAdornment';
import TextField from '@material-ui/core/TextField';
import Tooltip from '@material-ui/core/Tooltip';
import CloseIcon from '@material-ui/icons/Close';
import FilterIcon from '@material-ui/icons/KeyboardArrowDown';
import SearchIcon from '@material-ui/icons/Search';
import { ChangeEventHandler, default as React, useState } from 'react';
import { useMUITableContext } from '../MUITable';
import MUITableFilter from './Filters/MUITableFilter';
import Popover from './MUITablePopover';

const popStyles = (theme: Theme) =>
createStyles({
icon: {
'&:hover': {
color: theme.palette.primary.main
}
},
iconActive: {
color: theme.palette.primary.main
},
iconButton: {
padding: 7
},
pop: {
maxHeight: 400
}
});

export const FixedSearchPopover = (props: WithStyles<typeof popStyles>) => {
const { classes } = props;
const { options } = useMUITableContext();
const [active, setActive] = useState<boolean>(false);

return (
<Popover
open={active}
refExit={() => setActive(!active)}
className={classes.pop}
trigger={
<IconButton
data-testid={"fixed-search-filter"}
aria-label={options.translations.filter.title}
className={classes.iconButton}
classes={{ root: active ? classes.iconActive : classes.icon }}
onClick={() => setActive(!active)}
>
<Tooltip title={options.translations.filter.title}>
<FilterIcon />
</Tooltip>
</IconButton>
}
content={<MUITableFilter />}
/>
);
};

const FSPop = withStyles(popStyles, { withTheme: true })(FixedSearchPopover);

const searchStyles = (theme: Theme) =>
createStyles({
root: {
padding: '20px 0'
},
textField: {
margin: 0,
paddingTop: 10
},
input: {
padding: 0,
height: 46
},
notchedOutline: {
borderColor: `${theme.palette.grey['100']} !important`
},
cssFocused: {},
inputRoot: {
background: theme.palette.grey['100'],
border: 'none',
boxSizing: 'border-box',
borderRadius: 4,
'&$inputFocused $notchedOutline': {
borderColor: `white !important`,
boxShadow: theme.shadows[1]
}
},
inputFocused: {
background: theme.palette.common.white,
borderColor: `${theme.palette.divider} !important`
},
icon: {
color: theme.palette.text.secondary
},
iconButton: {
color: theme.palette.text.secondary,
padding: 7
},
wrapper: {
padding: 5,
justifyItems: 'flex-start',
alignItems: 'center',
display: 'flex'
},
adornment: {
marginLeft: 0
},
tabWrapper: {
borderTop: `1px solid ${theme.palette.divider}`,
borderBottom: `1px solid ${theme.palette.divider}`,
marginTop: 20
},
tab: {
'&:hover': {
background: theme.palette.grey['100']
}
},
customSelectWrap: {
position: 'absolute' as 'absolute',
width: '100%',
left: 0,
top: 0
}
});

const MUITableFixedSearch = (props: WithStyles<typeof searchStyles>) => {
const { classes } = props;
const { searchTextUpdate, search, options, toggleSearchVisible } = useMUITableContext();
const { title } = options;

// Event handler for text field
const onChange: ChangeEventHandler<any> = e => {
changeText(e.target.value ? e.target.value : null);
};
// Used by close button
const changeText = (text?: string) => {
if (!search.open && !!text) {
toggleSearchVisible();
}
searchTextUpdate(text ? text : '');
};

return (
<Grid
spacing={0}
container
className={classes.root}
alignItems={'center'}
data-testid={'FixedSearch'}
>
<Grid item xs={6}>
<Typography variant={'h5'} gutterBottom>
{title}
</Typography>
<TextField
data-testid="fixed-search"
className={classes.textField}
value={search.text ? search.text : ''}
onChange={onChange}
variant="outlined"
fullWidth
InputProps={{
inputProps: {
"data-testid": "fixed-search-input"
},
classes: {
root: classes.inputRoot,
focused: classes.inputFocused,
notchedOutline: classes.notchedOutline,
input: classes.input
},
startAdornment: (
<InputAdornment position="start">
<SearchIcon className={classes.icon} />
</InputAdornment>
),
endAdornment: (
<React.Fragment>
{search.text && search.text.length > 0 ? (
<InputAdornment position="end" className={classes.adornment}>
<IconButton
data-testid={"clear-fixed-search"}
id={"clear-fixed-search"}
className={classes.iconButton}
onClick={() => changeText()}
>
<CloseIcon />
</IconButton>
</InputAdornment>
) : null}
<InputAdornment position="end" className={classes.adornment}>
<FSPop />
</InputAdornment>
</React.Fragment>
)
}}
/>
</Grid>
</Grid>
);
};
export default withStyles(searchStyles, { withTheme: true, name: 'MUITableFixedSearch' })(
MUITableFixedSearch
);

0 comments on commit 06802bc

Please sign in to comment.