Skip to content

Commit 1362bed

Browse files
authored
feat(app-platform): Sort Integrations (#12697)
"Sentry Apps" and Integrations are now sorted among one another. First by Installed vs Uninstalled status, then alphabetically within each of those groupos.
1 parent ecb3d91 commit 1362bed

File tree

6 files changed

+325
-560
lines changed

6 files changed

+325
-560
lines changed

src/sentry/static/sentry/app/components/avatar/sentryAppAvatar.jsx

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/sentry/static/sentry/app/views/organizationIntegrations/index.jsx

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,9 @@ class OrganizationIntegrations extends AsyncComponent {
132132

133133
// Rendering
134134

135-
renderBody() {
136-
const {reloading, applications, appInstalls} = this.state;
137-
const providers = this.providers
138-
.sort((a, b) => b.isInstalled - a.isInstalled)
139-
.map(provider => (
135+
renderProvider(provider) {
136+
return (
137+
<IntegrationRow key={`row-${provider.key}`}>
140138
<ProviderRow
141139
key={provider.key}
142140
provider={provider}
@@ -148,7 +146,55 @@ class OrganizationIntegrations extends AsyncComponent {
148146
onReinstall={this.onInstall}
149147
enabledPlugins={this.enabledPlugins}
150148
/>
151-
));
149+
</IntegrationRow>
150+
);
151+
}
152+
153+
renderSentryApps(apps, key) {
154+
const {appInstalls} = this.state;
155+
156+
return (
157+
<IntegrationRow key={`row-${key}`}>
158+
<SentryAppInstallations
159+
key={key}
160+
orgId={this.props.params.orgId}
161+
installs={appInstalls}
162+
applications={apps}
163+
/>
164+
</IntegrationRow>
165+
);
166+
}
167+
168+
renderBody() {
169+
const {reloading, applications, appInstalls} = this.state;
170+
171+
const installedProviders = this.providers
172+
.filter(p => p.isInstalled)
173+
.map(p => [p.name, this.renderProvider(p)]);
174+
175+
const uninstalledProviders = this.providers
176+
.filter(p => !p.isInstalled)
177+
.map(p => [p.name, this.renderProvider(p)]);
178+
179+
const installedSentryApps = (applications || [])
180+
.filter(a => appInstalls.find(i => i.app.slug === a.slug))
181+
.map(a => [a.name, this.renderSentryApps([a], a.slug)]);
182+
183+
const uninstalledSentryApps = (applications || [])
184+
.filter(a => !appInstalls.find(i => i.app.slug === a.slug))
185+
.map(a => [a.name, this.renderSentryApps([a], a.slug)]);
186+
187+
// Combine the list of Providers and Sentry Apps that have installations.
188+
const installed = installedProviders
189+
.concat(installedSentryApps)
190+
.sort((a, b) => a[0].localeCompare(b[0]))
191+
.map(i => i[1]);
192+
193+
// Combine the list of Providers and Sentry Apps that have no installations.
194+
const uninstalled = uninstalledProviders
195+
.concat(uninstalledSentryApps)
196+
.sort((a, b) => a[0].localeCompare(b[0]))
197+
.map(i => i[1]);
152198

153199
return (
154200
<React.Fragment>
@@ -169,21 +215,17 @@ class OrganizationIntegrations extends AsyncComponent {
169215
{reloading && <StyledLoadingIndicator mini />}
170216
</PanelHeader>
171217
<PanelBody>
172-
{providers}
173-
{applications && (
174-
<SentryAppInstallations
175-
orgId={this.props.params.orgId}
176-
installs={appInstalls}
177-
applications={applications}
178-
/>
179-
)}
218+
{installed}
219+
{uninstalled}
180220
</PanelBody>
181221
</Panel>
182222
</React.Fragment>
183223
);
184224
}
185225
}
186226

227+
const IntegrationRow = styled.div``;
228+
187229
const StyledLoadingIndicator = styled(LoadingIndicator)`
188230
position: absolute;
189231
right: 7px;

src/sentry/static/sentry/app/views/settings/organizationDeveloperSettings/sentryApplicationRow.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Access from 'app/components/acl/access';
55
import Button from 'app/components/button';
66
import Confirm from 'app/components/confirm';
77
import ConfirmDelete from 'app/components/confirmDelete';
8-
import SentryAppAvatar from 'app/components/avatar/sentryAppAvatar';
98
import PropTypes from 'prop-types';
109
import SentryTypes from 'app/sentryTypes';
1110
import Tooltip from 'app/components/tooltip';
@@ -15,6 +14,7 @@ import styled from 'react-emotion';
1514
import space from 'app/styles/space';
1615
import {withTheme} from 'emotion-theming';
1716
import CircleIndicator from 'app/components/circleIndicator';
17+
import PluginIcon from 'app/plugins/components/pluginIcon';
1818

1919
export default class SentryApplicationRow extends React.PureComponent {
2020
static propTypes = {
@@ -72,7 +72,7 @@ export default class SentryApplicationRow extends React.PureComponent {
7272
return (
7373
<SentryAppItem>
7474
<StyledFlex>
75-
<SentryAppAvatar size={36} sentryApp={app} />
75+
<PluginIcon size={36} pluginId={app.slug} />
7676
<SentryAppBox>
7777
<SentryAppName>
7878
{showPublishStatus ? (

0 commit comments

Comments
 (0)