Skip to content

Commit 8c91607

Browse files
authored
fix(ui) Display implicit default sort and default to descending (#14042)
When switching sort columns it is preferrable to see the biggest value first. Each view has a default sort. Show that default sort in the sort buttons so that the user knows which direction the data is sorted by default. Refs SEN-845
1 parent 6220894 commit 8c91607

File tree

3 files changed

+61
-12
lines changed

3 files changed

+61
-12
lines changed

src/sentry/static/sentry/app/views/organizationEventsV2/sortLink.jsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,26 @@ class SortLink extends React.Component {
99
static propTypes = {
1010
title: PropTypes.string.isRequired,
1111
sortKey: PropTypes.string.isRequired,
12+
defaultSort: PropTypes.string.isRequired,
1213
location: PropTypes.object.isRequired,
1314
};
1415

16+
getCurrentSort() {
17+
const {defaultSort, location} = this.props;
18+
return location.query.sort ? location.query.sort : defaultSort;
19+
}
20+
1521
getSort() {
16-
const {sortKey, location} = this.props;
22+
const {sortKey} = this.props;
23+
const currentSort = this.getCurrentSort();
1724

1825
// Page is currently unsorted or is ascending
19-
if (!location.query.sort || location.query.sort === `-${sortKey}`) {
26+
if (currentSort === `-${sortKey}`) {
2027
return sortKey;
2128
}
29+
2230
// Reverse direction
23-
if (location.query.sort === sortKey) {
24-
return `-${sortKey}`;
25-
}
26-
return sortKey;
31+
return `-${sortKey}`;
2732
}
2833

2934
getTarget() {
@@ -35,12 +40,13 @@ class SortLink extends React.Component {
3540
}
3641

3742
renderChevron() {
38-
const {location, sortKey} = this.props;
39-
if (!location.query.sort || location.query.sort.indexOf(sortKey) === -1) {
43+
const currentSort = this.getCurrentSort();
44+
const {sortKey} = this.props;
45+
if (!currentSort || currentSort.indexOf(sortKey) === -1) {
4046
return null;
4147
}
4248

43-
if (location.query.sort[0] === '-') {
49+
if (currentSort[0] === '-') {
4450
return <InlineSvg src="icon-chevron-down" />;
4551
}
4652

src/sentry/static/sentry/app/views/organizationEventsV2/table.jsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import styled, {css} from 'react-emotion';
4+
import {omit} from 'lodash';
45

56
import SentryTypes from 'app/sentryTypes';
67
import {Panel, PanelHeader, PanelBody, PanelItem} from 'app/components/panels';
@@ -65,7 +66,8 @@ export default class Table extends React.Component {
6566

6667
render() {
6768
const {isLoading, location, view} = this.props;
68-
const {fields} = view.data;
69+
const {fields, sort} = view.data;
70+
const defaultSort = sort.length ? sort[0] : null;
6971

7072
return (
7173
<Panel>
@@ -84,7 +86,12 @@ export default class Table extends React.Component {
8486

8587
return (
8688
<HeaderItem key={field}>
87-
<SortLink sortKey={sortKey} title={title} location={location} />
89+
<SortLink
90+
defaultSort={defaultSort}
91+
sortKey={sortKey}
92+
title={title}
93+
location={location}
94+
/>
8895
</HeaderItem>
8996
);
9097
})}
@@ -128,6 +135,9 @@ const Cell = styled('div')`
128135
overflow: hidden;
129136
`;
130137

131-
const StyledPanelBody = styled(({isLoading, ...props}) => <PanelBody {...props} />)`
138+
const StyledPanelBody = styled(props => {
139+
const otherProps = omit(props, 'isLoading');
140+
return <PanelBody {...otherProps} />;
141+
})`
132142
${p => p.isLoading && 'min-height: 240px;'};
133143
`;

tests/js/spec/views/organizationEventsV2/index.spec.jsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,39 @@ describe('OrganizationEventsV2', function() {
6565
expect(content.text()).toContain('You need at least one project to use this view');
6666
});
6767

68+
it('generates an active sort link based on default sort', function() {
69+
const wrapper = mount(
70+
<OrganizationEventsV2
71+
organization={TestStubs.Organization({projects: [TestStubs.Project()]})}
72+
location={{query: {}}}
73+
router={{}}
74+
/>,
75+
TestStubs.routerContext()
76+
);
77+
78+
const findLink = sortKey =>
79+
wrapper
80+
.find('Table SortLink')
81+
.find({sortKey})
82+
.find('StyledLink');
83+
84+
const timestamp = findLink('timestamp');
85+
// Sort should be active
86+
expect(
87+
timestamp
88+
.find('InlineSvg')
89+
.first()
90+
.props().src
91+
).toEqual('icon-chevron-down');
92+
93+
// Sort link should reverse.
94+
expect(timestamp.props().to.query).toEqual({sort: 'timestamp'});
95+
96+
const userlink = findLink('user');
97+
// User link should be descending.
98+
expect(userlink.props().to.query).toEqual({sort: '-user'});
99+
});
100+
68101
it('generates links to modals', async function() {
69102
const wrapper = mount(
70103
<OrganizationEventsV2

0 commit comments

Comments
 (0)