diff --git a/client/app/components/items-list/ItemsList.tsx b/client/app/components/items-list/ItemsList.tsx index 4ef13790f4..c13cb809b4 100644 --- a/client/app/components/items-list/ItemsList.tsx +++ b/client/app/components/items-list/ItemsList.tsx @@ -28,6 +28,7 @@ export interface Controller { orderByField?: string; orderByReverse: boolean; toggleSorting: (orderByField: string) => void; + setSorting: (orderByField: string, orderByReverse: boolean) => void; // pagination page: number; @@ -139,10 +140,11 @@ export function wrap( this.props.onError!(error); const initialState = this.getState({ ...itemsSource.getState(), isLoaded: false }); - const { updatePagination, toggleSorting, updateSearch, updateSelectedTags, update, handleError } = itemsSource; + const { updatePagination, toggleSorting, setSorting, updateSearch, updateSelectedTags, update, handleError } = itemsSource; this.state = { ...initialState, toggleSorting, // eslint-disable-line react/no-unused-state + setSorting, // eslint-disable-line react/no-unused-state updateSearch: debounce(updateSearch, 200), // eslint-disable-line react/no-unused-state updateSelectedTags, // eslint-disable-line react/no-unused-state updatePagination, // eslint-disable-line react/no-unused-state diff --git a/client/app/components/items-list/classes/ItemsSource.js b/client/app/components/items-list/classes/ItemsSource.js index f32e8ee3a8..583541874c 100644 --- a/client/app/components/items-list/classes/ItemsSource.js +++ b/client/app/components/items-list/classes/ItemsSource.js @@ -39,14 +39,12 @@ export class ItemsSource { const customParams = {}; const context = { ...this.getCallbackContext(), - setCustomParams: params => { + setCustomParams: (params) => { extend(customParams, params); }, }; return this._beforeUpdate().then(() => { - const fetchToken = Math.random() - .toString(36) - .substr(2); + const fetchToken = Math.random().toString(36).substr(2); this._currentFetchToken = fetchToken; return this._fetcher .fetch(changes, state, context) @@ -59,7 +57,7 @@ export class ItemsSource { return this._afterUpdate(); } }) - .catch(error => this.handleError(error)); + .catch((error) => this.handleError(error)); }); } @@ -124,13 +122,20 @@ export class ItemsSource { }); }; - toggleSorting = orderByField => { + toggleSorting = (orderByField) => { this._sorter.toggleField(orderByField); this._savedOrderByField = this._sorter.field; this._changed({ sorting: true }); }; - updateSearch = searchTerm => { + setSorting = (orderByField, orderByReverse) => { + this._sorter.setField(orderByField); + this._sorter.setReverse(orderByReverse); + this._savedOrderByField = this._sorter.field; + this._changed({ sorting: true }); + }; + + updateSearch = (searchTerm) => { // here we update state directly, but later `fetchData` will update it properly this._searchTerm = searchTerm; // in search mode ignore the ordering and use the ranking order @@ -145,7 +150,7 @@ export class ItemsSource { this._changed({ search: true, pagination: { page: true } }); }; - updateSelectedTags = selectedTags => { + updateSelectedTags = (selectedTags) => { this._selectedTags = selectedTags; this._paginator.setPage(1); this._changed({ tags: true, pagination: { page: true } }); @@ -153,7 +158,7 @@ export class ItemsSource { update = () => this._changed(); - handleError = error => { + handleError = (error) => { if (isFunction(this.onError)) { this.onError(error); } @@ -172,7 +177,7 @@ export class ResourceItemsSource extends ItemsSource { processResults: (results, context) => { let processItem = getItemProcessor(context); processItem = isFunction(processItem) ? processItem : identity; - return map(results, item => processItem(item, context)); + return map(results, (item) => processItem(item, context)); }, }); } diff --git a/client/app/components/items-list/components/ItemsTable.jsx b/client/app/components/items-list/components/ItemsTable.jsx index 87e41ed180..496bb3c8cd 100644 --- a/client/app/components/items-list/components/ItemsTable.jsx +++ b/client/app/components/items-list/components/ItemsTable.jsx @@ -44,7 +44,7 @@ export const Columns = { date(overrides) { return extend( { - render: text => formatDate(text), + render: (text) => formatDate(text), }, overrides ); @@ -52,7 +52,7 @@ export const Columns = { dateTime(overrides) { return extend( { - render: text => formatDateTime(text), + render: (text) => formatDateTime(text), }, overrides ); @@ -62,7 +62,7 @@ export const Columns = { { width: "1%", className: "text-nowrap", - render: text => durationHumanize(text), + render: (text) => durationHumanize(text), }, overrides ); @@ -70,7 +70,7 @@ export const Columns = { timeAgo(overrides, timeAgoCustomProps = undefined) { return extend( { - render: value => , + render: (value) => , }, overrides ); @@ -110,6 +110,7 @@ export default class ItemsTable extends React.Component { orderByField: PropTypes.string, orderByReverse: PropTypes.bool, toggleSorting: PropTypes.func, + setSorting: PropTypes.func, "data-test": PropTypes.string, rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), }; @@ -127,18 +128,15 @@ export default class ItemsTable extends React.Component { }; prepareColumns() { - const { orderByField, orderByReverse, toggleSorting } = this.props; + const { orderByField, orderByReverse } = this.props; const orderByDirection = orderByReverse ? "descend" : "ascend"; return map( map( - filter(this.props.columns, column => (isFunction(column.isAvailable) ? column.isAvailable() : true)), - column => extend(column, { orderByField: column.orderByField || column.field }) + filter(this.props.columns, (column) => (isFunction(column.isAvailable) ? column.isAvailable() : true)), + (column) => extend(column, { orderByField: column.orderByField || column.field }) ), (column, index) => { - // Bind click events only to sortable columns - const onHeaderCell = column.sorter ? () => ({ onClick: () => toggleSorting(column.orderByField) }) : null; - // Wrap render function to pass correct arguments const render = isFunction(column.render) ? (text, row) => column.render(text, row.item) : identity; @@ -146,14 +144,13 @@ export default class ItemsTable extends React.Component { key: "column" + index, dataIndex: ["item", column.field], defaultSortOrder: column.orderByField === orderByField ? orderByDirection : null, - onHeaderCell, render, }); } ); } - getRowKey = record => { + getRowKey = (record) => { const { rowKey } = this.props; if (rowKey) { if (isFunction(rowKey)) { @@ -172,22 +169,43 @@ export default class ItemsTable extends React.Component { // Bind events only if `onRowClick` specified const onTableRow = isFunction(this.props.onRowClick) - ? row => ({ - onClick: event => { + ? (row) => ({ + onClick: (event) => { this.props.onRowClick(event, row.item); }, }) : null; + const onChange = (pagination, filters, sorter, extra) => { + const action = extra?.action; + if (action === "sort") { + const propsColumn = this.props.columns.find((column) => column.field === sorter.field[1]); + if (!propsColumn.sorter) { + return; + } + let orderByField = propsColumn.orderByField; + const orderByReverse = sorter.order === "descend"; + + if (orderByReverse === undefined) { + orderByField = null; + } + if (this.props.setSorting) { + this.props.setSorting(orderByField, orderByReverse); + } else { + this.props.toggleSorting(orderByField); + } + } + }; + const { showHeader } = this.props; if (this.props.loading) { if (isEmpty(tableDataProps.dataSource)) { - tableDataProps.columns = tableDataProps.columns.map(column => ({ + tableDataProps.columns = tableDataProps.columns.map((column) => ({ ...column, sorter: false, render: () => , })); - tableDataProps.dataSource = range(10).map(key => ({ key: `${key}` })); + tableDataProps.dataSource = range(10).map((key) => ({ key: `${key}` })); } else { tableDataProps.loading = { indicator: null }; } @@ -200,6 +218,7 @@ export default class ItemsTable extends React.Component { rowKey={this.getRowKey} pagination={false} onRow={onTableRow} + onChange={onChange} data-test={this.props["data-test"]} {...tableDataProps} /> diff --git a/client/app/pages/queries-list/QueriesList.jsx b/client/app/pages/queries-list/QueriesList.jsx index f49358d457..2a200e98b4 100644 --- a/client/app/pages/queries-list/QueriesList.jsx +++ b/client/app/pages/queries-list/QueriesList.jsx @@ -160,14 +160,15 @@ function QueriesList({ controller }) { orderByField={controller.orderByField} orderByReverse={controller.orderByReverse} toggleSorting={controller.toggleSorting} + setSorting={controller.setSorting} /> controller.updatePagination({ itemsPerPage })} + onPageSizeChange={(itemsPerPage) => controller.updatePagination({ itemsPerPage })} page={controller.page} - onChange={page => controller.updatePagination({ page })} + onChange={(page) => controller.updatePagination({ page })} /> @@ -196,7 +197,7 @@ const QueriesListPage = itemsList( }[currentPage]; }, getItemProcessor() { - return item => new Query(item); + return (item) => new Query(item); }, }), () => new UrlStateStorage({ orderByField: "created_at", orderByReverse: true }) @@ -207,7 +208,7 @@ routes.register( routeWithUserSession({ path: "/queries", title: "Queries", - render: pageProps => , + render: (pageProps) => , }) ); routes.register( @@ -215,7 +216,7 @@ routes.register( routeWithUserSession({ path: "/queries/favorites", title: "Favorite Queries", - render: pageProps => , + render: (pageProps) => , }) ); routes.register( @@ -223,7 +224,7 @@ routes.register( routeWithUserSession({ path: "/queries/archive", title: "Archived Queries", - render: pageProps => , + render: (pageProps) => , }) ); routes.register( @@ -231,6 +232,6 @@ routes.register( routeWithUserSession({ path: "/queries/my", title: "My Queries", - render: pageProps => , + render: (pageProps) => , }) );