Skip to content

Commit 84262fe

Browse files
Fix table item list ordering (#7366)
Fix query list item list sorting - descending order, no triangle mark - ascending order, up triangle mark(▲) - descending order, down triangle mark(▼) - ascending order, no triangle mark - descending order, up triangle mark(▲) - ascending order, down triangle mark(▼) - descending order, no triangle mark "sorting order" have 2-click cycle, but "triangle mark" have 3-click cycle.
1 parent 612eb8c commit 84262fe

File tree

4 files changed

+61
-34
lines changed

4 files changed

+61
-34
lines changed

client/app/components/items-list/ItemsList.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface Controller<I, P = any> {
2828
orderByField?: string;
2929
orderByReverse: boolean;
3030
toggleSorting: (orderByField: string) => void;
31+
setSorting: (orderByField: string, orderByReverse: boolean) => void;
3132

3233
// pagination
3334
page: number;
@@ -139,10 +140,11 @@ export function wrap<I, P = any>(
139140
this.props.onError!(error);
140141

141142
const initialState = this.getState({ ...itemsSource.getState(), isLoaded: false });
142-
const { updatePagination, toggleSorting, updateSearch, updateSelectedTags, update, handleError } = itemsSource;
143+
const { updatePagination, toggleSorting, setSorting, updateSearch, updateSelectedTags, update, handleError } = itemsSource;
143144
this.state = {
144145
...initialState,
145146
toggleSorting, // eslint-disable-line react/no-unused-state
147+
setSorting, // eslint-disable-line react/no-unused-state
146148
updateSearch: debounce(updateSearch, 200), // eslint-disable-line react/no-unused-state
147149
updateSelectedTags, // eslint-disable-line react/no-unused-state
148150
updatePagination, // eslint-disable-line react/no-unused-state

client/app/components/items-list/classes/ItemsSource.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,12 @@ export class ItemsSource {
3939
const customParams = {};
4040
const context = {
4141
...this.getCallbackContext(),
42-
setCustomParams: params => {
42+
setCustomParams: (params) => {
4343
extend(customParams, params);
4444
},
4545
};
4646
return this._beforeUpdate().then(() => {
47-
const fetchToken = Math.random()
48-
.toString(36)
49-
.substr(2);
47+
const fetchToken = Math.random().toString(36).substr(2);
5048
this._currentFetchToken = fetchToken;
5149
return this._fetcher
5250
.fetch(changes, state, context)
@@ -59,7 +57,7 @@ export class ItemsSource {
5957
return this._afterUpdate();
6058
}
6159
})
62-
.catch(error => this.handleError(error));
60+
.catch((error) => this.handleError(error));
6361
});
6462
}
6563

@@ -124,13 +122,20 @@ export class ItemsSource {
124122
});
125123
};
126124

127-
toggleSorting = orderByField => {
125+
toggleSorting = (orderByField) => {
128126
this._sorter.toggleField(orderByField);
129127
this._savedOrderByField = this._sorter.field;
130128
this._changed({ sorting: true });
131129
};
132130

133-
updateSearch = searchTerm => {
131+
setSorting = (orderByField, orderByReverse) => {
132+
this._sorter.setField(orderByField);
133+
this._sorter.setReverse(orderByReverse);
134+
this._savedOrderByField = this._sorter.field;
135+
this._changed({ sorting: true });
136+
};
137+
138+
updateSearch = (searchTerm) => {
134139
// here we update state directly, but later `fetchData` will update it properly
135140
this._searchTerm = searchTerm;
136141
// in search mode ignore the ordering and use the ranking order
@@ -145,15 +150,15 @@ export class ItemsSource {
145150
this._changed({ search: true, pagination: { page: true } });
146151
};
147152

148-
updateSelectedTags = selectedTags => {
153+
updateSelectedTags = (selectedTags) => {
149154
this._selectedTags = selectedTags;
150155
this._paginator.setPage(1);
151156
this._changed({ tags: true, pagination: { page: true } });
152157
};
153158

154159
update = () => this._changed();
155160

156-
handleError = error => {
161+
handleError = (error) => {
157162
if (isFunction(this.onError)) {
158163
this.onError(error);
159164
}
@@ -172,7 +177,7 @@ export class ResourceItemsSource extends ItemsSource {
172177
processResults: (results, context) => {
173178
let processItem = getItemProcessor(context);
174179
processItem = isFunction(processItem) ? processItem : identity;
175-
return map(results, item => processItem(item, context));
180+
return map(results, (item) => processItem(item, context));
176181
},
177182
});
178183
}

client/app/components/items-list/components/ItemsTable.jsx

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ export const Columns = {
4444
date(overrides) {
4545
return extend(
4646
{
47-
render: text => formatDate(text),
47+
render: (text) => formatDate(text),
4848
},
4949
overrides
5050
);
5151
},
5252
dateTime(overrides) {
5353
return extend(
5454
{
55-
render: text => formatDateTime(text),
55+
render: (text) => formatDateTime(text),
5656
},
5757
overrides
5858
);
@@ -62,15 +62,15 @@ export const Columns = {
6262
{
6363
width: "1%",
6464
className: "text-nowrap",
65-
render: text => durationHumanize(text),
65+
render: (text) => durationHumanize(text),
6666
},
6767
overrides
6868
);
6969
},
7070
timeAgo(overrides, timeAgoCustomProps = undefined) {
7171
return extend(
7272
{
73-
render: value => <TimeAgo date={value} {...timeAgoCustomProps} />,
73+
render: (value) => <TimeAgo date={value} {...timeAgoCustomProps} />,
7474
},
7575
overrides
7676
);
@@ -110,6 +110,7 @@ export default class ItemsTable extends React.Component {
110110
orderByField: PropTypes.string,
111111
orderByReverse: PropTypes.bool,
112112
toggleSorting: PropTypes.func,
113+
setSorting: PropTypes.func,
113114
"data-test": PropTypes.string,
114115
rowKey: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
115116
};
@@ -127,33 +128,29 @@ export default class ItemsTable extends React.Component {
127128
};
128129

129130
prepareColumns() {
130-
const { orderByField, orderByReverse, toggleSorting } = this.props;
131+
const { orderByField, orderByReverse } = this.props;
131132
const orderByDirection = orderByReverse ? "descend" : "ascend";
132133

133134
return map(
134135
map(
135-
filter(this.props.columns, column => (isFunction(column.isAvailable) ? column.isAvailable() : true)),
136-
column => extend(column, { orderByField: column.orderByField || column.field })
136+
filter(this.props.columns, (column) => (isFunction(column.isAvailable) ? column.isAvailable() : true)),
137+
(column) => extend(column, { orderByField: column.orderByField || column.field })
137138
),
138139
(column, index) => {
139-
// Bind click events only to sortable columns
140-
const onHeaderCell = column.sorter ? () => ({ onClick: () => toggleSorting(column.orderByField) }) : null;
141-
142140
// Wrap render function to pass correct arguments
143141
const render = isFunction(column.render) ? (text, row) => column.render(text, row.item) : identity;
144142

145143
return extend(omit(column, ["field", "orderByField", "render"]), {
146144
key: "column" + index,
147145
dataIndex: ["item", column.field],
148146
defaultSortOrder: column.orderByField === orderByField ? orderByDirection : null,
149-
onHeaderCell,
150147
render,
151148
});
152149
}
153150
);
154151
}
155152

156-
getRowKey = record => {
153+
getRowKey = (record) => {
157154
const { rowKey } = this.props;
158155
if (rowKey) {
159156
if (isFunction(rowKey)) {
@@ -172,22 +169,43 @@ export default class ItemsTable extends React.Component {
172169

173170
// Bind events only if `onRowClick` specified
174171
const onTableRow = isFunction(this.props.onRowClick)
175-
? row => ({
176-
onClick: event => {
172+
? (row) => ({
173+
onClick: (event) => {
177174
this.props.onRowClick(event, row.item);
178175
},
179176
})
180177
: null;
181178

179+
const onChange = (pagination, filters, sorter, extra) => {
180+
const action = extra?.action;
181+
if (action === "sort") {
182+
const propsColumn = this.props.columns.find((column) => column.field === sorter.field[1]);
183+
if (!propsColumn.sorter) {
184+
return;
185+
}
186+
let orderByField = propsColumn.orderByField;
187+
const orderByReverse = sorter.order === "descend";
188+
189+
if (orderByReverse === undefined) {
190+
orderByField = null;
191+
}
192+
if (this.props.setSorting) {
193+
this.props.setSorting(orderByField, orderByReverse);
194+
} else {
195+
this.props.toggleSorting(orderByField);
196+
}
197+
}
198+
};
199+
182200
const { showHeader } = this.props;
183201
if (this.props.loading) {
184202
if (isEmpty(tableDataProps.dataSource)) {
185-
tableDataProps.columns = tableDataProps.columns.map(column => ({
203+
tableDataProps.columns = tableDataProps.columns.map((column) => ({
186204
...column,
187205
sorter: false,
188206
render: () => <Skeleton active paragraph={false} />,
189207
}));
190-
tableDataProps.dataSource = range(10).map(key => ({ key: `${key}` }));
208+
tableDataProps.dataSource = range(10).map((key) => ({ key: `${key}` }));
191209
} else {
192210
tableDataProps.loading = { indicator: null };
193211
}
@@ -200,6 +218,7 @@ export default class ItemsTable extends React.Component {
200218
rowKey={this.getRowKey}
201219
pagination={false}
202220
onRow={onTableRow}
221+
onChange={onChange}
203222
data-test={this.props["data-test"]}
204223
{...tableDataProps}
205224
/>

client/app/pages/queries-list/QueriesList.jsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,15 @@ function QueriesList({ controller }) {
160160
orderByField={controller.orderByField}
161161
orderByReverse={controller.orderByReverse}
162162
toggleSorting={controller.toggleSorting}
163+
setSorting={controller.setSorting}
163164
/>
164165
<Paginator
165166
showPageSizeSelect
166167
totalCount={controller.totalItemsCount}
167168
pageSize={controller.itemsPerPage}
168-
onPageSizeChange={itemsPerPage => controller.updatePagination({ itemsPerPage })}
169+
onPageSizeChange={(itemsPerPage) => controller.updatePagination({ itemsPerPage })}
169170
page={controller.page}
170-
onChange={page => controller.updatePagination({ page })}
171+
onChange={(page) => controller.updatePagination({ page })}
171172
/>
172173
</div>
173174
</React.Fragment>
@@ -196,7 +197,7 @@ const QueriesListPage = itemsList(
196197
}[currentPage];
197198
},
198199
getItemProcessor() {
199-
return item => new Query(item);
200+
return (item) => new Query(item);
200201
},
201202
}),
202203
() => new UrlStateStorage({ orderByField: "created_at", orderByReverse: true })
@@ -207,30 +208,30 @@ routes.register(
207208
routeWithUserSession({
208209
path: "/queries",
209210
title: "Queries",
210-
render: pageProps => <QueriesListPage {...pageProps} currentPage="all" />,
211+
render: (pageProps) => <QueriesListPage {...pageProps} currentPage="all" />,
211212
})
212213
);
213214
routes.register(
214215
"Queries.Favorites",
215216
routeWithUserSession({
216217
path: "/queries/favorites",
217218
title: "Favorite Queries",
218-
render: pageProps => <QueriesListPage {...pageProps} currentPage="favorites" />,
219+
render: (pageProps) => <QueriesListPage {...pageProps} currentPage="favorites" />,
219220
})
220221
);
221222
routes.register(
222223
"Queries.Archived",
223224
routeWithUserSession({
224225
path: "/queries/archive",
225226
title: "Archived Queries",
226-
render: pageProps => <QueriesListPage {...pageProps} currentPage="archive" />,
227+
render: (pageProps) => <QueriesListPage {...pageProps} currentPage="archive" />,
227228
})
228229
);
229230
routes.register(
230231
"Queries.My",
231232
routeWithUserSession({
232233
path: "/queries/my",
233234
title: "My Queries",
234-
render: pageProps => <QueriesListPage {...pageProps} currentPage="my" />,
235+
render: (pageProps) => <QueriesListPage {...pageProps} currentPage="my" />,
235236
})
236237
);

0 commit comments

Comments
 (0)