Skip to content

fix(environments): Fix project environment data not being loaded #13676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/sentry/static/sentry/app/utils/environment.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {toTitleCase} from 'app/utils';

const DEFAULT_EMPTY_ROUTING_NAME = 'none';
const DEFAULT_EMPTY_ENV_NAME = '(No Environment)';

export function getUrlRoutingName(env) {
return encodeURIComponent(env.name) || DEFAULT_EMPTY_ROUTING_NAME;
}

export function getDisplayName(env) {
return toTitleCase(env.name) || DEFAULT_EMPTY_ENV_NAME;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import {Flex} from 'grid-emotion';
import PropTypes from 'prop-types';
import React from 'react';
import Reflux from 'reflux';
import createReactClass from 'create-react-class';
import styled from 'react-emotion';

import {ALL_ENVIRONMENTS_KEY} from 'app/constants';
import {Panel, PanelHeader, PanelBody, PanelItem} from 'app/components/panels';
import {addErrorMessage, addSuccessMessage} from 'app/actionCreators/indicator';
import {
loadActiveEnvironments,
loadHiddenEnvironments,
} from 'app/actionCreators/environments';
import {t, tct} from 'app/locale';
import Access from 'app/components/acl/access';
import withApi from 'app/utils/withApi';
import Button from 'app/components/button';
import EmptyMessage from 'app/views/settings/components/emptyMessage';
import EnvironmentStore from 'app/stores/environmentStore';
import ListLink from 'app/components/links/listLink';
import LoadingIndicator from 'app/components/loadingIndicator';
import NavTabs from 'app/components/navTabs';
Expand All @@ -26,6 +20,7 @@ import SentryTypes from 'app/sentryTypes';
import SettingsPageHeader from 'app/views/settings/components/settingsPageHeader';
import recreateRoute from 'app/utils/recreateRoute';
import space from 'app/styles/space';
import {getUrlRoutingName, getDisplayName} from 'app/utils/environment';

const ProjectEnvironments = createReactClass({
propTypes: {
Expand All @@ -34,64 +29,41 @@ const ProjectEnvironments = createReactClass({
params: PropTypes.object,
},

mixins: [Reflux.listenTo(EnvironmentStore, 'onEnvironmentsChange')],

getInitialState() {
const isHidden = this.props.location.pathname.endsWith('hidden/');
const environments = isHidden
? EnvironmentStore.getHidden()
: EnvironmentStore.getActive();

return {
project: null,
environments,
isHidden,
environments: null,
isLoading: true,
};
},

componentDidMount() {
if (this.state.environments === null) {
this.fetchData(this.state.isHidden);
}
this.fetchData();
},

// Fetch project details instead of using project context to guarantee we have latest project details
this.fetchProjectDetails();
componentDidUpdate(prevProps) {
if (
this.props.location.pathname.endsWith('hidden/') !==
prevProps.location.pathname.endsWith('hidden/')
) {
this.fetchData();
}
},

componentWillReceiveProps(nextProps) {
fetchData() {
const isHidden = this.props.location.pathname.endsWith('hidden/');
const environments = isHidden
? EnvironmentStore.getHidden()
: EnvironmentStore.getActive();

this.setState(
{
isHidden,
environments,
},
() => {
if (environments === null) {
this.fetchData(isHidden);
}
}
);
},

refetchAll() {
this.fetchData(true);
this.fetchData(false);
this.fetchProjectDetails();
},
if (!this.state.isLoading) {
this.setState({isLoading: true});
}

fetchData(hidden) {
const {orgId, projectId} = this.props.params;
this.props.api.request(`/projects/${orgId}/${projectId}/environments/`, {
query: {
visibility: hidden ? 'hidden' : 'visible',
visibility: isHidden ? 'hidden' : 'visible',
},
success: env => {
const load = hidden ? loadHiddenEnvironments : loadActiveEnvironments;
load(env);
success: environments => {
this.setState({environments, isLoading: false});
},
});
},
Expand All @@ -105,22 +77,12 @@ const ProjectEnvironments = createReactClass({
});
},

onEnvironmentsChange() {
const {isHidden} = this.state;

this.setState({
environments: isHidden
? EnvironmentStore.getHidden()
: EnvironmentStore.getActive(),
});
},

// Toggle visibility of environment
toggleEnv(env, shouldHide) {
const {orgId, projectId} = this.props.params;

this.props.api.request(
`/projects/${orgId}/${projectId}/environments/${env.urlRoutingName}/`,
`/projects/${orgId}/${projectId}/environments/${getUrlRoutingName(env)}/`,
{
method: 'PUT',
data: {
Expand All @@ -130,24 +92,24 @@ const ProjectEnvironments = createReactClass({
success: e => {
addSuccessMessage(
tct('Updated [environment]', {
environment: env.displayName,
environment: getDisplayName(env),
})
);
},
error: err => {
addErrorMessage(
tct('Unable to update [environment]', {
environment: env.displayName,
environment: getDisplayName(env),
})
);
},
complete: this.refetchAll,
complete: this.fetchData,
}
);
},

renderEmpty() {
const {isHidden} = this.state;
const isHidden = this.props.location.pathname.endsWith('hidden/');
const message = isHidden
? t("You don't have any hidden environments.")
: t("You don't have any environments yet.");
Expand All @@ -160,17 +122,17 @@ const ProjectEnvironments = createReactClass({
* - "No Environment"
*
*/
renderSystemRows() {
renderAllEnvironmentsSystemRow() {
// Not available in "Hidden" tab
if (this.state.isHidden) {
const isHidden = this.props.location.pathname.endsWith('hidden/');
if (isHidden) {
return null;
}
return (
<EnvironmentRow
name={ALL_ENVIRONMENTS_KEY}
environment={{
id: ALL_ENVIRONMENTS_KEY,
displayName: t('All Environments'),
name: ALL_ENVIRONMENTS_KEY,
}}
isSystemRow
Expand All @@ -179,12 +141,12 @@ const ProjectEnvironments = createReactClass({
},

renderEnvironmentList(envs) {
const {isHidden} = this.state;
const isHidden = this.props.location.pathname.endsWith('hidden/');
const buttonText = isHidden ? t('Show') : t('Hide');

return (
<React.Fragment>
{this.renderSystemRows()}
{this.renderAllEnvironmentsSystemRow()}
{envs.map(env => {
return (
<EnvironmentRow
Expand All @@ -202,29 +164,37 @@ const ProjectEnvironments = createReactClass({
);
},

render() {
const {environments} = this.state;
const {routes, params} = this.props;
renderBody() {
const {environments, isLoading} = this.state;

if (environments === null) {
if (isLoading) {
return <LoadingIndicator />;
}

return (
<PanelBody>
{environments.length
? this.renderEnvironmentList(environments)
: this.renderEmpty()}
</PanelBody>
);
},

render() {
const {routes, params, location} = this.props;
const isHidden = location.pathname.endsWith('hidden/');

const baseUrl = recreateRoute('', {routes, params, stepBack: -1});
return (
<div>
<SettingsPageHeader
title={t('Manage Environments')}
tabs={
<NavTabs underlined={true}>
<ListLink to={baseUrl} index={true} isActive={() => !this.state.isHidden}>
<ListLink to={baseUrl} index={true} isActive={() => !isHidden}>
{t('Environments')}
</ListLink>
<ListLink
to={`${baseUrl}hidden/`}
index={true}
isActive={() => this.state.isHidden}
>
<ListLink to={`${baseUrl}hidden/`} index={true} isActive={() => isHidden}>
{t('Hidden')}
</ListLink>
</NavTabs>
Expand All @@ -233,15 +203,8 @@ const ProjectEnvironments = createReactClass({
<PermissionAlert />

<Panel>
<PanelHeader>
{this.state.isHidden ? t('Hidden') : t('Active Environments')}
</PanelHeader>

<PanelBody>
{environments.length
? this.renderEnvironmentList(environments)
: this.renderEmpty()}
</PanelBody>
<PanelHeader>{isHidden ? t('Hidden') : t('Active Environments')}</PanelHeader>
{this.renderBody()}
</Panel>
</div>
);
Expand All @@ -264,7 +227,7 @@ class EnvironmentRow extends React.Component {
return (
<PanelItem align="center" justify="space-between">
<Flex align="center">
{isSystemRow ? environment.displayName : environment.name}
{isSystemRow ? t('All Environments') : environment.name}
</Flex>
<Access access={['project:write']}>
{({hasAccess}) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1167,10 +1167,9 @@ exports[`ProjectEnvironments render hidden renders environment list 1`] = `
actionText="Show"
environment={
Object {
"displayName": "Zzz",
"id": "1",
"isHidden": true,
"name": "zzz",
"urlRoutingName": "zzz",
}
}
isHidden={true}
Expand Down
Loading