• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gregnb / mui-datatables / #1869

17 Dec 2018 07:23PM UTC coverage: 78.18% (+0.06%) from 78.118%
#1869

push

gregnb
Fix issue with sort not taking into account on re-render (#316)

271 of 377 branches covered (71.88%)

Branch coverage included in aggregate %.

5 of 9 new or added lines in 1 file covered. (55.56%)

42 existing lines in 3 files now uncovered.

442 of 535 relevant lines covered (82.62%)

42.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/MUIDataTableToolbar.js
1
import React from "react";
2
import Typography from "@material-ui/core/Typography";
3
import Toolbar from "@material-ui/core/Toolbar";
4
import Tooltip from "@material-ui/core/Tooltip";
5
import IconButton from "@material-ui/core/IconButton";
6
import MUIDataTableFilter from "./MUIDataTableFilter";
7
import MUIDataTableViewCol from "./MUIDataTableViewCol";
8
import MUIDataTableSearch from "./MUIDataTableSearch";
9
import SearchIcon from "@material-ui/icons/Search";
10
import DownloadIcon from "@material-ui/icons/CloudDownload";
11
import PrintIcon from "@material-ui/icons/Print";
12
import ViewColumnIcon from "@material-ui/icons/ViewColumn";
13
import FilterIcon from "@material-ui/icons/FilterList";
14
import ReactToPrint from "react-to-print";
15
import styled from "./styled";
16
import MUIDataTablePopoverWrapper from "./MUIPopover/MUIDataTablePopoverWrapper";
17

18
export const defaultToolbarStyles = (theme, props) => ({
14✔
19
  root: {},
20
  left: {
21
    flex: "1 1 55%",
22
  },
23
  actions: {
24
    flex: "0 0 45%",
25
    textAlign: "right",
26
  },
27
  titleRoot: {},
28
  titleText: {},
29
  icon: {
30
    "&:hover": {
31
      color: "#307BB0",
32
    },
33
  },
34
  iconActive: {
35
    color: "#307BB0",
36
  },
37
  searchIcon: {
38
    display: "inline-flex",
39
    marginTop: "10px",
40
    marginRight: "8px",
41
  },
42
  ...(props.options.responsive ? { ...responsiveToolbarStyles(theme) } : {}),
14✔
43
});
44

45
export const responsiveToolbarStyles = theme => ({
4✔
46
  [theme.breakpoints.down("sm")]: {
47
    titleRoot: {},
48
    titleText: {
49
      fontSize: "16px",
50
    },
51
    spacer: {
52
      display: "none",
53
    },
54
    left: {
55
      // flex: "1 1 40%",
56
      padding: "8px 0px",
57
    },
58
    actions: {
59
      // flex: "1 1 60%",
60
      textAlign: "right",
61
    },
62
  },
63
  [theme.breakpoints.down("xs")]: {
64
    root: {
65
      display: "block",
66
    },
67
    left: {
68
      padding: "8px 0px 0px 0px",
69
    },
70
    titleText: {
71
      textAlign: "center",
72
    },
73
    actions: {
74
      textAlign: "center",
75
    },
76
  },
77
  "@media screen and (max-width: 480px)": {},
78
});
79

80
class MUIDataTableToolbar extends React.Component {
81
  state = {
82
    iconActive: null,
83
    showSearch: false,
84
  };
85

86
  handleCSVDownload = () => {
87
    const { data, columns, options } = this.props;
1✔
88

89
    const CSVHead =
90
      columns
1✔
91
        .reduce(
92
          (soFar, column) =>
93
            column.download ? soFar + '"' + column.name + '"' + options.downloadOptions.separator : soFar,
4!
94
          "",
95
        )
96
        .slice(0, -1) + "\r\n";
97

98
    const CSVBody = data
1✔
99
      .reduce(
100
        (soFar, row) =>
101
          soFar +
4✔
102
          '"' +
103
          row.data
104
            .filter((field, index) => columns[index].download)
16✔
105
            .join('"' + options.downloadOptions.separator + '"') +
106
          '"\r\n',
107
        [],
108
      )
109
      .trim();
110

111
    /* taken from react-csv */
112
    const csv = `${CSVHead}${CSVBody}`;
1✔
113
    const blob = new Blob([csv], { type: "text/csv" });
1✔
114

115
    if (navigator && navigator.msSaveOrOpenBlob) {
1!
116
      navigator.msSaveOrOpenBlob(blob, options.downloadOptions.filename);
×
117
    } else {
118
      const dataURI = `data:text/csv;charset=utf-8,${csv}`;
1✔
119

120
      const URL = window.URL || window.webkitURL;
1!
121
      const downloadURI = typeof URL.createObjectURL === "undefined" ? dataURI : URL.createObjectURL(blob);
1!
122

123
      let link = document.createElement("a");
1✔
124
      link.setAttribute("href", downloadURI);
1✔
125
      link.setAttribute("download", options.downloadOptions.filename);
1✔
126
      document.body.appendChild(link);
1✔
127
      link.click();
1✔
128
      document.body.removeChild(link);
1✔
129
    }
130
  };
131

132
  setActiveIcon = iconName => {
133
    this.setState(() => ({
3✔
134
      iconActive: iconName,
135
      showSearch: iconName === "search" ? this.handleShowSearch() : false,
3✔
136
    }));
137
  };
138

139
  getActiveIcon = (styles, iconName) => {
140
    return this.state.iconActive !== iconName ? styles.icon : styles.iconActive;
60✔
141
  };
142

143
  handleShowSearch = () => {
144
    !!this.props.options.onSearchOpen && this.props.options.onSearchOpen();
2!
145
    this.props.setTableAction("onSearchOpen");
2✔
146
    return true;
2✔
147
  };
148

149
  hideSearch = () => {
150
    const { onSearchClose } = this.props.options;
1✔
151

152
    if (onSearchClose) onSearchClose();
1!
153
    this.props.searchTextUpdate(null);
1✔
154

155
    this.setState(() => ({
1✔
156
      iconActive: null,
157
      showSearch: false,
158
    }));
159

160
    this.searchButton.focus();
1✔
161
  };
162

163
  render() {
164
    const {
165
      data,
166
      options,
167
      classes,
168
      columns,
169
      filterData,
170
      filterList,
171
      filterUpdate,
172
      resetFilters,
173
      searchTextUpdate,
174
      toggleViewColumn,
175
      title,
176
      tableRef,
177
    } = this.props;
21✔
178

179
    const { search, downloadCsv, print, viewColumns, filterTable } = options.textLabels.toolbar;
21✔
180
    const { showSearch } = this.state;
21✔
181

182
    return (
21✔
183
      <Toolbar className={classes.root} role={"toolbar"} aria-label={"Table Toolbar"}>
184
        <div className={classes.left}>
185
          {showSearch === true ? (
21✔
186
            <MUIDataTableSearch onSearch={searchTextUpdate} onHide={this.hideSearch} options={options} />
187
          ) : (
188
            <div className={classes.titleRoot} aria-hidden={"true"}>
189
              <Typography variant="h6" className={classes.titleText}>
190
                {title}
191
              </Typography>
192
            </div>
193
          )}
194
        </div>
195
        <div className={classes.actions}>
196
          {options.search && (
41✔
197
            <Tooltip title={search}>
198
              <IconButton
199
                aria-label={search}
200
                buttonRef={el => (this.searchButton = el)}
15✔
201
                classes={{ root: this.getActiveIcon(classes, "search") }}
202
                onClick={this.setActiveIcon.bind(null, "search")}>
203
                <SearchIcon />
204
              </IconButton>
205
            </Tooltip>
206
          )}
207

208
          {options.download && (
41✔
209
            <Tooltip title={downloadCsv}>
210
              <IconButton aria-label={downloadCsv} classes={{ root: classes.icon }} onClick={this.handleCSVDownload}>
211
                <DownloadIcon />
212
              </IconButton>
213
            </Tooltip>
214
          )}
215

216
          {options.print && (
41✔
217
            <Tooltip title={print}>
218
              <span>
219
                <ReactToPrint
220
                  trigger={() => (
221
                    <IconButton aria-label={print} classes={{ root: classes.icon }}>
12✔
222
                      <PrintIcon />
223
                    </IconButton>
224
                  )}
UNCOV
225
                  content={() => this.props.tableRef()}
×
226
                />
227
              </span>
228
            </Tooltip>
229
          )}
230

231
          {options.viewColumns && (
41✔
232
            <MUIDataTablePopoverWrapper
233
              label={viewColumns}
234
              tableRef={tableRef}
235
              onClick={this.setActiveIcon.bind(null, "viewcolumns")}
236
              buttonRoot={this.getActiveIcon(classes, "viewcolumns")}
237
              icon={<ViewColumnIcon />}
238
              classes={classes}>
239
              <MUIDataTableViewCol data={data} columns={columns} options={options} onColumnUpdate={toggleViewColumn} />
240
            </MUIDataTablePopoverWrapper>
241
          )}
242

243
          {options.filter && (
41✔
244
            <MUIDataTablePopoverWrapper
245
              label={filterTable}
246
              tableRef={tableRef}
247
              onClick={this.setActiveIcon.bind(null, "filter")}
248
              buttonRoot={this.getActiveIcon(classes, "filter")}
249
              icon={<FilterIcon />}
250
              classes={classes}>
251
              <MUIDataTableFilter
252
                columns={columns}
253
                options={options}
254
                filterList={filterList}
255
                filterData={filterData}
256
                onFilterUpdate={filterUpdate}
257
                onFilterReset={resetFilters}
258
              />
259
            </MUIDataTablePopoverWrapper>
260
          )}
261
          {options.customToolbar ? options.customToolbar() : false}
21!
262
        </div>
263
      </Toolbar>
264
    );
265
  }
266
}
267

268
export default styled(MUIDataTableToolbar)(defaultToolbarStyles, { name: "MUIDataTableToolbar" });
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc