import * as React from 'react'; import { DefaultTooltip } from 'cbioportal-frontend-commons'; import { Button, ButtonGroup, ButtonToolbar } from 'react-bootstrap'; var ClipboardButton = require('react-clipboard.js'); var Clipboard = require('clipboard'); import fileDownload from 'react-file-download'; import _ from 'lodash'; import { PaginationControls, IPaginationControlsProps, } from '../paginationControls/PaginationControls'; import { If } from 'react-if'; import { IColumnVisibilityControlsProps, ColumnVisibilityControls, } from '../columnVisibilityControls/ColumnVisibilityControls'; import { computed } from 'mobx'; import { AppContext } from 'cbioportal-frontend-commons'; export interface ITableHeaderControlsProps { tableData?: Array; className?: string; searchClassName?: string; showSearch?: boolean; showCopyAndDownload?: boolean; copyDownloadClassName?: string; showHideShowColumnButton?: boolean; showPagination?: boolean; handleInput?: Function; downloadDataGenerator?: Function; downloadDataContainsHeader?: boolean; downloadFilename?: string; paginationProps?: IPaginationControlsProps; columnVisibilityProps?: IColumnVisibilityControlsProps; searchDelayMs?: number; } function serializeTableData(tableData: Array, containsHeader?: boolean) { let content: Array = []; let delim = ','; if (!containsHeader) { // try to get the header from object keys in case no header provided // if contains header, assuming that the first element represents the header values Object.keys(tableData[0]).forEach((col: any) => content.push(col, delim) ); content.pop(); content.push('\r\n'); } tableData.forEach((row: any) => { _.each(row, (cell: string) => { content.push(cell, delim); }); content.pop(); content.push('\r\n'); }); return content.join(''); } export default class TableHeaderControls extends React.Component< ITableHeaderControlsProps, {} > { private searchTimeout: number | null; private _copyButton: HTMLElement; constructor(props: ITableHeaderControlsProps) { super(props); this.handleInput = this.handleInput.bind(this); this.getText = this.getText.bind(this); } componentDidMount() { // this is necessary because the clipboard wrapper library // doesn't work with tooltips :( if (this.showCopyAndDownload && this._copyButton) { this.bindCopyButton(); } } public bindCopyButton() { new Clipboard(this._copyButton, { text: function() { return this.getText(); }.bind(this), }); } public static defaultProps: ITableHeaderControlsProps = { showSearch: false, showCopyAndDownload: true, showPagination: false, searchClassName: '', copyDownloadClassName: '', downloadFilename: 'patient-clinical-attributes.tsv', downloadDataContainsHeader: false, paginationProps: {}, columnVisibilityProps: {}, searchDelayMs: 400, }; @computed get showCopyAndDownload() { return ( this.props.showCopyAndDownload && this.context.showDownloadControls === true ); } public handleInput(evt: any) { if (this.searchTimeout !== null) { clearTimeout(this.searchTimeout); this.searchTimeout = null; } const filterValue = evt.currentTarget.value; this.searchTimeout = setTimeout(() => { if (this.props.handleInput) { this.props.handleInput(filterValue); } }, this.props.searchDelayMs); } public render() { const arrowContent =
; return (
Copy} placement="top" mouseLeaveDelay={0} mouseEnterDelay={0.5} arrowContent={arrowContent} > Download CSV} mouseLeaveDelay={0} mouseEnterDelay={0.5} placement="top" arrowContent={arrowContent} >
); } public getText() { if (this.props.downloadDataGenerator) { return serializeTableData( this.props.downloadDataGenerator() || [], this.props.downloadDataContainsHeader ); } else { return serializeTableData( this.props.tableData || [], this.props.downloadDataContainsHeader ); } } private downloadData = () => { if (this.props.downloadDataGenerator) { fileDownload( serializeTableData( this.props.downloadDataGenerator() || [], this.props.downloadDataContainsHeader ), this.props.downloadFilename ); } else { fileDownload( serializeTableData( this.props.tableData || [], this.props.downloadDataContainsHeader ), this.props.downloadFilename ); } }; } TableHeaderControls.contextType = AppContext;