Skip to content

Commit

Permalink
convention
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed May 31, 2021
1 parent a248e6c commit d4c40b4
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,44 @@ import MenuItem from '@material-ui/core/MenuItem';
import { isHideMenuKey, isTabKey } from '../../utils/keyboardUtils';
import { GridApiContext } from '../GridApiContext';
import { GridMenu } from '../menu/GridMenu';
import { GridExportOption, GridExportFormat, GridExportConfiguration } from '../../models';
import { GridExportCsvOptions } from '../../models/gridExport';

type GridToolbarExportProps = ButtonProps & { exportConfiguration?: GridExportConfiguration };
interface GridExportFormatCsv {
format: 'csv';
formatOptions?: GridExportCsvOptions;
}

type GridExportFormatOption = GridExportFormatCsv;

type GridExportOption = GridExportFormatOption & {
label: React.ReactNode;
};

export interface GridToolbarExportProps extends ButtonProps {
csvOptions?: GridExportCsvOptions;
}

export const GridToolbarExport = React.forwardRef<HTMLButtonElement, GridToolbarExportProps>(
function GridToolbarExport({ exportConfiguration, ...other }, ref) {
function GridToolbarExport(props, ref) {
const { csvOptions, ...other } = props;
const apiRef = React.useContext(GridApiContext);
const exportButtonId = useId();
const exportMenuId = useId();
const buttonId = useId();
const menuId = useId();
const [anchorEl, setAnchorEl] = React.useState(null);
const ExportIcon = apiRef!.current.components!.ExportIcon!;

const ExportOptions: Array<GridExportOption> = [];

ExportOptions.push({
const exportOptions: Array<GridExportOption> = [];
exportOptions.push({
label: apiRef!.current.getLocaleText('toolbarExportCSV'),
format: 'csv',
options: exportConfiguration?.csv,
formatOptions: csvOptions,
});

const handleExportSelectorOpen = (event) => setAnchorEl(event.currentTarget);
const handleExportSelectorClose = () => setAnchorEl(null);
const handleExport = (option: GridExportFormat, fileName?: string) => {
const handleMenuOpen = (event) => setAnchorEl(event.currentTarget);
const handleMenuClose = () => setAnchorEl(null);
const handleExport = (option: GridExportFormatOption) => () => {
if (option.format === 'csv') {
apiRef!.current.exportDataAsCsv(option.options, fileName);
apiRef!.current.exportDataAsCsv(option.formatOptions);
}

setAnchorEl(null);
Expand All @@ -42,46 +55,44 @@ export const GridToolbarExport = React.forwardRef<HTMLButtonElement, GridToolbar
event.preventDefault();
}
if (isHideMenuKey(event.key)) {
handleExportSelectorClose();
handleMenuClose();
}
};

const renderExportOptions: Array<React.ReactElement> = ExportOptions.map((option, index) => (
<MenuItem key={index} onClick={() => handleExport(option, exportConfiguration?.fileName)}>
{option.label}
</MenuItem>
));

return (
<React.Fragment>
<Button
ref={ref}
color="primary"
size="small"
startIcon={<ExportIcon />}
onClick={handleExportSelectorOpen}
onClick={handleMenuOpen}
aria-expanded={anchorEl ? 'true' : undefined}
aria-haspopup="menu"
aria-labelledby={exportMenuId}
id={exportButtonId}
aria-labelledby={menuId}
id={buttonId}
{...other}
>
{apiRef!.current.getLocaleText('toolbarExport')}
</Button>
<GridMenu
open={Boolean(anchorEl)}
target={anchorEl}
onClickAway={handleExportSelectorClose}
onClickAway={handleMenuClose}
position="bottom-start"
>
<MenuList
id={exportMenuId}
id={menuId}
className="MuiDataGrid-gridMenuList"
aria-labelledby={exportButtonId}
aria-labelledby={buttonId}
onKeyDown={handleListKeyDown}
autoFocusItem={Boolean(anchorEl)}
>
{renderExportOptions}
{exportOptions.map((option, index) => (
<MenuItem key={index} onClick={handleExport(option)}>
{option.label}
</MenuItem>
))}
</MenuList>
</GridMenu>
</React.Fragment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useGridSelector } from '../core/useGridSelector';
import { visibleGridColumnsSelector } from '../columns';
import { visibleSortedGridRowsSelector } from '../filter';
import { gridSelectionStateSelector } from '../selection';
import { GridCsvExportApi, GridExportCsvOptions } from '../../../models';
import { GridCsvExportApi } from '../../../models';
import { useLogger } from '../../utils/useLogger';
import { exportAs } from '../../../utils';
import { buildCSV } from './seralizers/csvSeraliser';
Expand All @@ -22,19 +22,13 @@ export const useGridCsvExport = (apiRef: GridApiRef): void => {
return buildCSV(visibleColumns, visibleSortedRows, selection, apiRef.current.getCellValue);
}, [logger, visibleColumns, visibleSortedRows, selection, apiRef]);

const exportDataAsCsv = React.useCallback(
(options?: GridExportCsvOptions, fileName?: string): void => {
logger.debug(`Export data as CSV`);
const csv = getDataAsCsv();
const exportDataAsCsv = React.useCallback((): void => {
logger.debug(`Export data as CSV`);
const csv = getDataAsCsv();
const blob = new Blob([csv], { type: 'text/csv' });

const blob = new Blob([options?.utf8WithBom ? new Uint8Array([0xef, 0xbb, 0xbf]) : '', csv], {
type: 'text/csv',
});

exportAs(blob, 'csv', fileName?.length ? fileName : undefined);
},
[logger, getDataAsCsv],
);
exportAs(blob, 'csv', 'data');
}, [logger, getDataAsCsv]);

const csvExportApi: GridCsvExportApi = {
getDataAsCsv,
Expand Down
16 changes: 10 additions & 6 deletions packages/grid/_modules_/grid/models/api/gridCsvExportApi.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { GridExportCsvOptions } from '../gridExport';

/**
* The csv export API interface that is available in the grid [[apiRef]].
* The CSV export API interface that is available in the grid [[apiRef]].
*/
export interface GridCsvExportApi {
/**
* Returns the grid data formatted as CSV.
* @returns {string} The data as CSV.
* Returns the grid data as a CSV string.
* This method is used internally by `exportDataAsCsv`.
* @params GridExportCsvOptions The options to apply on the export.
* @returns string
*/
getDataAsCsv: () => string;
getDataAsCsv: (options?: GridExportCsvOptions) => string;
/**
* Exports the grid data as CSV and sends it to the user.
* Downloads and exports a CSV of the grid's data.
* @params GridExportCsvOptions The options to apply on the export.
* @returns void
*/
exportDataAsCsv: (options?: GridExportCsvOptions, fileName?: string) => void;
exportDataAsCsv: (options?: GridExportCsvOptions) => void;
}
22 changes: 5 additions & 17 deletions packages/grid/_modules_/grid/models/gridExport.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
export interface GridExportCsvOptions {
utf8WithBom?: boolean;
}
export interface GridExportFormatCsv {
format: 'csv';
options?: GridExportCsvOptions;
}

/**
* Available export formats. To be extended in future.
* The options to apply on the CSV export.
*/
export type GridExportFormatExtension = 'csv';
export type GridExportFormat = GridExportFormatCsv;
export interface GridExportConfiguration {
export interface GridExportCsvOptions {
fileName?: string;
csv?: GridExportCsvOptions;
utf8WithBom?: boolean;
}

/**
* Export option interface
* Available export formats.
*/
export type GridExportOption = GridExportFormat & {
label: React.ReactNode;
};
export type GridExportFormat = 'csv';
4 changes: 2 additions & 2 deletions packages/grid/_modules_/grid/utils/exportAs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GridExportFormatExtension } from '../models/gridExport';
import { GridExportFormat } from '../models/gridExport';

/**
* I have hesitate to use https://github.com/eligrey/FileSaver.js.
Expand All @@ -12,7 +12,7 @@ import { GridExportFormatExtension } from '../models/gridExport';
*/
export function exportAs(
blob: Blob,
extension: GridExportFormatExtension = 'csv',
extension: GridExportFormat = 'csv',
filename: string = document.title,
): void {
const fullName = `${filename}.${extension}`;
Expand Down

0 comments on commit d4c40b4

Please sign in to comment.