| 1 |
import React, { Component } from 'react'; |
| 2 |
import ReactTable from 'react-table'; |
| 3 |
import 'react-table/react-table.css'; |
| 4 |
|
| 5 |
import '../../css/admin/manage/table.scss'; |
| 6 |
|
| 7 |
import { __wpupg } from 'Shared/Translations'; |
| 8 |
import ErrorBoundary from 'Shared/ErrorBoundary'; |
| 9 |
import SelectColumns from './general/SelectColumns'; |
| 10 |
import Api from 'Shared/Api'; |
| 11 |
import Totals from './general/Totals'; |
| 12 |
|
| 13 |
const initState = { |
| 14 |
data: [], |
| 15 |
pages: null, |
| 16 |
filtered: [], |
| 17 |
countFiltered: false, |
| 18 |
countTotal: false, |
| 19 |
loading: true, |
| 20 |
columns: [], |
| 21 |
selectedColumns: false, |
| 22 |
selectedRows: {}, |
| 23 |
selectedAllRows: 0, |
| 24 |
}; |
| 25 |
|
| 26 |
export default class DataTable extends Component { |
| 27 |
constructor(props) { |
| 28 |
super(props); |
| 29 |
|
| 30 |
this.state = { |
| 31 |
...initState, |
| 32 |
}; |
| 33 |
|
| 34 |
this.initDataTable = this.initDataTable.bind(this); |
| 35 |
this.refreshData = this.refreshData.bind(this); |
| 36 |
this.fetchData = this.fetchData.bind(this); |
| 37 |
this.toggleSelectRow = this.toggleSelectRow.bind(this); |
| 38 |
this.toggleSelectAll = this.toggleSelectAll.bind(this); |
| 39 |
this.getSelectedRows = this.getSelectedRows.bind(this); |
| 40 |
this.onColumnsChange = this.onColumnsChange.bind(this); |
| 41 |
this.requirementMet = this.requirementMet.bind(this); |
| 42 |
} |
| 43 |
|
| 44 |
componentDidMount() { |
| 45 |
this.initDataTable(); |
| 46 |
} |
| 47 |
|
| 48 |
componentDidUpdate( prevProps ) { |
| 49 |
if ( this.props.type !== prevProps.type ) { |
| 50 |
this.initDataTable( true ); |
| 51 |
} |
| 52 |
} |
| 53 |
|
| 54 |
initDataTable( forceRefresh = false ) { |
| 55 |
// Only init when requirement is met. |
| 56 |
if ( ! this.requirementMet() ) { |
| 57 |
return; |
| 58 |
} |
| 59 |
|
| 60 |
// Use default selectedColumns or restore from LocalStorage. |
| 61 |
let selectedColumns = this.props.options.selectedColumns; |
| 62 |
|
| 63 |
if ( false !== selectedColumns ) { |
| 64 |
let savedSelectedColumns = localStorage.getItem( `wpupg-admin-manage-${ this.props.options.id }-columns` ); |
| 65 |
|
| 66 |
if ( savedSelectedColumns ) { |
| 67 |
savedSelectedColumns = JSON.parse(savedSelectedColumns); |
| 68 |
|
| 69 |
if (Array.isArray(savedSelectedColumns)) { |
| 70 |
selectedColumns = savedSelectedColumns; |
| 71 |
} |
| 72 |
} |
| 73 |
} |
| 74 |
|
| 75 |
this.setState({ |
| 76 |
...initState, |
| 77 |
columns: this.props.options.columns.getColumns( this ), |
| 78 |
selectedColumns: selectedColumns, |
| 79 |
}, () => { |
| 80 |
if ( forceRefresh ) { |
| 81 |
this.refreshData(); |
| 82 |
} |
| 83 |
}); |
| 84 |
} |
| 85 |
|
| 86 |
toggleSelectRow(id) { |
| 87 |
let newSelected = { ...this.state.selectedRows }; |
| 88 |
|
| 89 |
newSelected[id] = !newSelected[id]; |
| 90 |
|
| 91 |
const nbrSelected = Object.values(newSelected).filter(value => value).length; |
| 92 |
let selectedAllRows = 2; |
| 93 |
|
| 94 |
if ( 0 === nbrSelected ) { |
| 95 |
selectedAllRows = 0; |
| 96 |
} else if ( this.state.data.length === nbrSelected ) { |
| 97 |
selectedAllRows = 1; |
| 98 |
} |
| 99 |
|
| 100 |
this.setState({ |
| 101 |
selectedRows: newSelected, |
| 102 |
selectedAllRows, |
| 103 |
}); |
| 104 |
} |
| 105 |
|
| 106 |
toggleSelectAll() { |
| 107 |
const bulkEditKey = 'categories' === this.props.options.route ? 'term_id' : 'id'; |
| 108 |
let newSelected = {}; |
| 109 |
|
| 110 |
if ( 0 === this.state.selectedAllRows ) { |
| 111 |
for ( let row of this.state.data ) { |
| 112 |
newSelected[ row[ bulkEditKey ] ] = true; |
| 113 |
} |
| 114 |
} |
| 115 |
|
| 116 |
this.setState({ |
| 117 |
selectedRows: newSelected, |
| 118 |
selectedAllRows: 0 === this.state.selectedAllRows ? 1 : 0, |
| 119 |
}); |
| 120 |
} |
| 121 |
|
| 122 |
getSelectedRows() { |
| 123 |
return Object.keys(this.state.selectedRows).filter(id => this.state.selectedRows[id]).map(id => parseInt(id)); |
| 124 |
} |
| 125 |
|
| 126 |
refreshData() { |
| 127 |
if ( this.refReactTable ) { |
| 128 |
this.refReactTable.fireFetchData(); |
| 129 |
} |
| 130 |
} |
| 131 |
|
| 132 |
fetchData(state, instance) { |
| 133 |
const currentData = state.data; |
| 134 |
|
| 135 |
this.setState({ |
| 136 |
loading: true, |
| 137 |
}, () => { |
| 138 |
if ( this.requirementMet() ) { |
| 139 |
Api.manage.getData({ |
| 140 |
route: this.props.options.route, |
| 141 |
type: this.props.options.id, |
| 142 |
pageSize: state.pageSize, |
| 143 |
page: state.page, |
| 144 |
sorted: state.sorted, |
| 145 |
filtered: state.filtered, |
| 146 |
}).then(data => { |
| 147 |
if ( data ) { |
| 148 |
let newState = { |
| 149 |
data: data.rows, |
| 150 |
pages: data.pages, |
| 151 |
countFiltered: data.filtered, |
| 152 |
countTotal: data.total, |
| 153 |
loading: false, |
| 154 |
}; |
| 155 |
|
| 156 |
const bulkEditKey = 'taxonomy' === this.props.options.route ? 'term_id' : 'id'; |
| 157 |
if ( JSON.stringify( data.rows.map( row => row[ bulkEditKey ] ) ) !== JSON.stringify( currentData.map( row => row[ bulkEditKey ] ) ) ) { |
| 158 |
newState.selectedRows = {}; |
| 159 |
newState.selectedAllRows = 0; |
| 160 |
} |
| 161 |
|
| 162 |
this.setState(newState); |
| 163 |
} |
| 164 |
}); |
| 165 |
} |
| 166 |
}); |
| 167 |
} |
| 168 |
|
| 169 |
onColumnsChange(id, checked) { |
| 170 |
let selectedColumns = [ ...this.state.selectedColumns ]; |
| 171 |
|
| 172 |
if (checked) { |
| 173 |
selectedColumns.push(id); |
| 174 |
} else { |
| 175 |
selectedColumns = selectedColumns.filter(c => c !== id); |
| 176 |
} |
| 177 |
|
| 178 |
this.setState({ |
| 179 |
selectedColumns |
| 180 |
}); |
| 181 |
|
| 182 |
localStorage.setItem( `wpupg-admin-manage-${ this.props.options.id }-columns`, JSON.stringify( selectedColumns ) ); |
| 183 |
} |
| 184 |
|
| 185 |
requirementMet() { |
| 186 |
if ( this.props.options.hasOwnProperty( 'required' ) && ( ! wpupg_admin.addons.hasOwnProperty( this.props.options.required ) || true !== wpupg_admin.addons[ this.props.options.required ] ) ) { |
| 187 |
return false; |
| 188 |
} |
| 189 |
|
| 190 |
return true; |
| 191 |
} |
| 192 |
|
| 193 |
render() { |
| 194 |
if ( ! this.props.options ) { |
| 195 |
return null; |
| 196 |
} |
| 197 |
|
| 198 |
// Check if Premium requirement is met. |
| 199 |
if ( ! this.requirementMet() ) { |
| 200 |
const bundle = this.props.options.required[0].toUpperCase() + this.props.options.required.substring(1); |
| 201 |
|
| 202 |
return ( |
| 203 |
<div className="wpupg-admin-manage-requirement"> |
| 204 |
<div>*{ __wpupg( 'This feature is only available in' ) }</div> |
| 205 |
<a href="https://bootstrapped.ventures/wp-ultimate-post-grid/get-the-plugin/" target="_blank"> |
| 206 |
{ `WP Ultimate Post Grid ${bundle} Bundle` } |
| 207 |
</a> |
| 208 |
</div> |
| 209 |
); |
| 210 |
} |
| 211 |
|
| 212 |
const { data, pages, loading } = this.state; |
| 213 |
const selectedColumns = this.state.columns.filter(column => 'actions' === column.id || false === this.state.selectedColumns || this.state.selectedColumns.includes(column.id)); |
| 214 |
const filteredColumns = this.state.filtered.filter( filter => '' !== filter.value && 'all' !== filter.value ).map( filter => filter.id ); |
| 215 |
|
| 216 |
return ( |
| 217 |
<div className="wpupg-admin-manage-page"> |
| 218 |
{ |
| 219 |
false !== this.state.selectedColumns |
| 220 |
|| this.props.options.bulkEdit |
| 221 |
|| this.props.options.createButton |
| 222 |
? |
| 223 |
<div className="wpupg-admin-manage-header"> |
| 224 |
{ |
| 225 |
false === this.state.selectedColumns |
| 226 |
? |
| 227 |
<div></div> |
| 228 |
: |
| 229 |
<SelectColumns |
| 230 |
onColumnsChange={this.onColumnsChange} |
| 231 |
columns={this.state.columns} |
| 232 |
selectedColumns={this.state.selectedColumns} |
| 233 |
filteredColumns={filteredColumns} |
| 234 |
/> |
| 235 |
} |
| 236 |
<div className="wpupg-admin-manage-header-buttons"> |
| 237 |
{ |
| 238 |
( false === this.state.selectedColumns || this.state.selectedColumns.includes( 'bulk_edit' ) ) |
| 239 |
&& this.props.options.bulkEdit |
| 240 |
&& <button |
| 241 |
className="button" |
| 242 |
onClick={ () => { |
| 243 |
WPUPG_Modal.open( 'bulk-edit', { |
| 244 |
route: this.props.options.bulkEdit.route, |
| 245 |
type: this.props.options.bulkEdit.type, |
| 246 |
ids: this.getSelectedRows(), |
| 247 |
saveCallback: () => this.refreshData(), |
| 248 |
} ); |
| 249 |
}} |
| 250 |
disabled={ 0 === this.getSelectedRows().length } |
| 251 |
>{ __wpupg( 'Bulk Edit' ) } { this.getSelectedRows().length } { 1 === this.getSelectedRows().length ? this.props.options.label.singular : this.props.options.label.plural }...</button> |
| 252 |
} |
| 253 |
{ |
| 254 |
this.props.options.createButton |
| 255 |
? |
| 256 |
<button |
| 257 |
className="button button-primary" |
| 258 |
onClick={ () => this.props.options.createButton( this ) } |
| 259 |
>{ `${__wpupg( 'Create' )} ${ this.props.options.label.singular }` }</button> |
| 260 |
: |
| 261 |
null |
| 262 |
} |
| 263 |
</div> |
| 264 |
</div> |
| 265 |
: |
| 266 |
null |
| 267 |
} |
| 268 |
<div className="wpupg-admin-manage-table-container"> |
| 269 |
<ErrorBoundary module="Datatable"> |
| 270 |
<Totals |
| 271 |
filtered={this.state.countFiltered} |
| 272 |
total={this.state.countTotal} |
| 273 |
/> |
| 274 |
<div className="wpupg-admin-manage-table-inner"> |
| 275 |
<ReactTable |
| 276 |
ref={(refReactTable) => {this.refReactTable = refReactTable;}} |
| 277 |
manual |
| 278 |
columns={selectedColumns} |
| 279 |
data={ data } |
| 280 |
pages={pages} |
| 281 |
filtered={this.state.filtered} |
| 282 |
onFilteredChange={ filtered => { |
| 283 |
this.setState( { filtered } ); |
| 284 |
} } |
| 285 |
loading={ loading } |
| 286 |
onFetchData={this.fetchData} |
| 287 |
defaultPageSize={ this.props.options.hasOwnProperty( 'defaultPageSize' ) ? this.props.options.defaultPageSize : 25 } |
| 288 |
pageSizeOptions={ [5, 10, 20, 25, 50, 100, 500] } |
| 289 |
defaultSorted={[{ |
| 290 |
id: 'id', |
| 291 |
desc: true |
| 292 |
}]} |
| 293 |
filterable |
| 294 |
resizable={false} |
| 295 |
className="wpupg-admin-manage-table wpupg-admin-table -highlight" |
| 296 |
/> |
| 297 |
</div> |
| 298 |
</ErrorBoundary> |
| 299 |
</div> |
| 300 |
</div> |
| 301 |
); |
| 302 |
} |
| 303 |
} |