Skip to content
This repository has been archived by the owner on May 6, 2024. It is now read-only.

Commit

Permalink
ref: Update to latest react, redux, and various supporting libs
Browse files Browse the repository at this point in the history
  • Loading branch information
dcramer committed Nov 11, 2019
1 parent ae487ee commit 2a30a03
Show file tree
Hide file tree
Showing 14 changed files with 493 additions and 188 deletions.
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
"xhr-mock": "^2.4.1"
},
"dependencies": {
"@sentry/browser": "^5.5.0",
"@sentry/integrations": "^5.5.0",
"@sentry/browser": "^5.8.0",
"@sentry/integrations": "^5.8.0",
"autoprefixer": "7.1.1",
"babel-core": "6.25.0",
"babel-loader": "^7.1.2",
Expand Down Expand Up @@ -59,25 +59,25 @@
"postcss-loader": "2.0.6",
"promise": "7.1.1",
"prop-types": "^15.6.2",
"react": "^16.5.1",
"react": "^16.11.0",
"react-chartjs-2": "^2.7.4",
"react-dev-utils": "^3.1.2",
"react-document-title": "^2.0.3",
"react-dom": "16.4.2",
"react-dom": "^16.11.0",
"react-gravatar": "^2.6.3",
"react-icon-base": "^2.0.8",
"react-icons": "^2.2.7",
"react-loadable": "^5.3.1",
"react-redux": "^5.0.5",
"react-router": "3.2.0",
"react-redux": "^7.1.3",
"react-router": "3",
"react-select": "^1.0.0-rc.10",
"react-syntax-highlighter": "^6.1.1",
"react-test-renderer": "^16.2.0",
"react-transition-group": "^2.4.0",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0",
"react-transition-group": "^4.3.0",
"redux": "^4.0.4",
"redux-thunk": "^2.3.0",
"style-loader": "0.18.2",
"styled-components": "^2.1.1",
"styled-components": "^4.4.1",
"sw-precache-webpack-plugin": "^0.11.4",
"url-loader": "0.5.9",
"webpack": "^3.6.0",
Expand Down
18 changes: 9 additions & 9 deletions webapp/components/AsyncComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,20 @@ export default class AsyncComponent extends Component {
};
}

componentWillMount() {
componentDidMount() {
this.api = new Client();
this.reloadData();
}

componentWillReceiveProps(nextProps, nextContext) {
let isRouterInContext = !!nextContext.router;
let isLocationInProps = nextProps.location !== undefined;
componentDidUpdate(prevProps) {
let isRouterInContext = !!this.context.router;
let isLocationInProps = this.props.location !== undefined;

let prevLocation = isLocationInProps ? this.props.location : this.state.__location;
let prevLocation = isLocationInProps ? prevProps.location : this.state.__location;
let currentLocation = isLocationInProps
? nextProps.location
? this.props.location
: isRouterInContext
? nextContext.router.location
? this.context.router.location
: null;

if (!(currentLocation && prevLocation)) {
Expand All @@ -60,11 +60,11 @@ export default class AsyncComponent extends Component {

if (
currentLocation.pathname !== prevLocation.pathname ||
!isEqual(this.props.params, nextProps.params) ||
!isEqual(this.props.params, prevProps.params) ||
currentLocation.search !== prevLocation.search ||
currentLocation.state !== prevLocation.state
) {
this.remountComponent(nextProps, nextContext);
this.remountComponent(this.props, this.context);
}
}

Expand Down
7 changes: 0 additions & 7 deletions webapp/components/AsyncPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,13 @@ import PropTypes from 'prop-types';

import AsyncComponent from './AsyncComponent';

import {Client} from '../api';

// TODO(dcramer): make this simply call AsyncComponent instead of extend
export default class AsyncPage extends AsyncComponent {
static propTypes = {
params: PropTypes.object,
location: PropTypes.object
};

componentWillMount() {
this.api = new Client();
this.reloadData();
}

// XXX: cant call this getInitialState as React whines
getDefaultState(props, context) {
let endpoints = this.getEndpoints(props, context);
Expand Down
25 changes: 12 additions & 13 deletions webapp/components/ErrorBoundary.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {Component} from 'react';
import PropTypes from 'prop-types';
import idx from 'idx';
import {isEqual} from 'lodash';
import {withRouter} from 'react-router';
// This is being pulled form the CDN currently
// import Raven from 'raven-js';

Expand All @@ -11,34 +12,30 @@ import NetworkError from './NetworkError';
import NotFoundError from './NotFoundError';
import * as errors from '../errors';

export default class ErrorBoundary extends Component {
static contextTypes = {
router: PropTypes.object
};

class ErrorBoundary extends Component {
static propTypes = {
router: PropTypes.object,
children: PropTypes.node,
location: PropTypes.object
};

constructor(...params) {
super(...params);
this.state = {error: null, location: null};
this.state = {error: null, lastLocation: null};
}

componentWillReceiveProps(nextProps, nextContext) {
let {router} = nextContext;
if (!isEqual(this.state.location, router.location)) {
this.setState({error: null, location: null});
static getDerivedStateFromProps(props, state) {
let {router} = props;
if (!isEqual(state.location, router.location)) {
return {error: null, lastLocation: null};
}
super.componentWillReceiveProps &&
super.componentWillReceiveProps(nextProps, nextContext);
return null;
}

componentDidCatch(error, errorInfo) {
this.setState({
error,
location: {...(idx(this.context.router, _ => _.location) || {})}
lastLocation: {...(idx(this.props.router, _ => _.location) || {})}
});
if (window.Raven) {
window.Sentry.captureException(error, {extra: errorInfo});
Expand Down Expand Up @@ -83,3 +80,5 @@ export default class ErrorBoundary extends Component {
}
}
}

export default withRouter(ErrorBoundary);
7 changes: 2 additions & 5 deletions webapp/components/Indicators.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {connect} from 'react-redux';
import ToastIndicator from './ToastIndicator';

const FadeTransition = props => (
<CSSTransition {...props} classNames="fade" timeout={500} />
<CSSTransition {...props} unmountOnExit classNames="fade" timeout={300} />
);

class Indicators extends Component {
Expand All @@ -17,10 +17,7 @@ class Indicators extends Component {
render() {
return (
<div>
<TransitionGroup
transitionName="toast"
transitionEnter={false}
transitionLeaveTimeout={500}>
<TransitionGroup enter={false}>
{this.props.items.map(indicator => {
return (
<FadeTransition key={indicator.id}>
Expand Down
6 changes: 5 additions & 1 deletion webapp/components/ToastIndicator.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@
.fade-exit {
opacity: 1;
}
.fade-enter-active {
opacity: 1;
transition: opacity 200ms;
}
.fade-exit-active {
opacity: 0.01;
transition: opacity 500ms ease-in;
transition: opacity 200ms;
}

.toast.loading.toast-message {
Expand Down
21 changes: 12 additions & 9 deletions webapp/pages/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ObjectDuration from '../components/ObjectDuration';
import {Column, Header, ResultGrid, Row} from '../components/ResultGrid';
import Section from '../components/Section';
import SectionHeading from '../components/SectionHeading';
import requireAuth from '../utils/requireAuth';

const RepoLink = styled(Link)`
display: block;
Expand All @@ -30,6 +31,15 @@ const RepoLink = styled(Link)`
}
`;

const Name = styled.div`
font-size: 15px;
line-height: 1.2;
font-weight: 500;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
`;

class RepoListSection extends AsyncComponent {
static propTypes = {
repoList: PropTypes.array
Expand Down Expand Up @@ -159,7 +169,7 @@ const WrappedBuildList = connect(
{fetchBuilds}
)(subscribe(() => ['builds'])(BuildListSection));

export default class Dashboard extends AsyncPage {
class Dashboard extends AsyncPage {
getTitle() {
return 'Zeus Dashboard';
}
Expand All @@ -180,11 +190,4 @@ export default class Dashboard extends AsyncPage {
}
}

const Name = styled.div`
font-size: 15px;
line-height: 1.2;
font-weight: 500;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
`;
export default requireAuth(Dashboard);
5 changes: 4 additions & 1 deletion webapp/pages/OwnerDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {ResourceNotFound} from '../errors';
import AsyncPage from '../components/AsyncPage';
import Layout from '../components/Layout';
import ResultGrid from '../components/ResultGrid';
import requireAuth from '../utils/requireAuth';

export default class OwnerDetails extends AsyncPage {
class OwnerDetails extends AsyncPage {
static contextTypes = {
...AsyncPage.contextTypes,
repoList: PropTypes.arrayOf(PropTypes.object).isRequired
Expand Down Expand Up @@ -59,3 +60,5 @@ export default class OwnerDetails extends AsyncPage {
);
}
}

export default requireAuth(OwnerDetails);
5 changes: 4 additions & 1 deletion webapp/pages/RepositoryDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import PropTypes from 'prop-types';
import AsyncPage from '../components/AsyncPage';
import RepositoryContent from '../components/RepositoryContent';
import RepositoryHeader from '../components/RepositoryHeader';
import requireAuth from '../utils/requireAuth';

export default class RepositoryDetails extends AsyncPage {
class RepositoryDetails extends AsyncPage {
static contextTypes = {
...AsyncPage.contextTypes,
repoList: PropTypes.arrayOf(PropTypes.object).isRequired
Expand Down Expand Up @@ -57,3 +58,5 @@ export default class RepositoryDetails extends AsyncPage {
);
}
}

export default requireAuth(RepositoryDetails);
5 changes: 4 additions & 1 deletion webapp/pages/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import AsyncPage from '../components/AsyncPage';
import Content from '../components/Content';
import Header from '../components/Header';
import Nav, {NavItem} from '../components/Nav';
import requireAuth from '../utils/requireAuth';

export default class Settings extends AsyncPage {
class Settings extends AsyncPage {
static contextTypes = {
repoList: PropTypes.arrayOf(PropTypes.object).isRequired,
router: PropTypes.object.isRequired
Expand Down Expand Up @@ -36,3 +37,5 @@ export default class Settings extends AsyncPage {
return this.props.children;
}
}

export default requireAuth(Settings);
29 changes: 16 additions & 13 deletions webapp/pages/UserBuildList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import BuildList from '../components/BuildList';
import Layout from '../components/Layout';
import Paginator from '../components/Paginator';
import Section from '../components/Section';
import requireAuth from '../utils/requireAuth';

class UserBuildList extends AsyncPage {
getTitle() {
Expand Down Expand Up @@ -62,16 +63,18 @@ class BuildListBody extends AsyncComponent {
}
}

export default connect(
({auth, builds}) => {
let emailSet = new Set((auth.emails || []).map(e => e.email));
return {
buildList: builds.items
.filter(build => !!build.repository && emailSet.has(build.source.author.email))
.slice(0, 25),
links: builds.links,
loading: !builds.loaded
};
},
{fetchBuilds}
)(subscribe(() => ['builds'])(UserBuildList));
export default requireAuth(
connect(
({auth, builds}) => {
let emailSet = new Set((auth.emails || []).map(e => e.email));
return {
buildList: builds.items
.filter(build => !!build.repository && emailSet.has(build.source.author.email))
.slice(0, 25),
links: builds.links,
loading: !builds.loaded
};
},
{fetchBuilds}
)(subscribe(() => ['builds'])(UserBuildList))
);
14 changes: 5 additions & 9 deletions webapp/routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ import Login from './components/Login';
import NotFoundError from './components/NotFoundError';
import PageLoading from './components/PageLoading';

import requireAuth from './utils/requireAuth';

const AsyncSettings = Loadable({
loader: () => import('./pages/Settings'),
loading: PageLoading
Expand All @@ -70,19 +68,17 @@ export default (
<Route path="/" component={App}>
<IndexRoute component={DashboardOrWelcome} />
<Route path="/welcome" component={Welcome} />
<Route path="/dashboard" component={requireAuth(Dashboard)} />
<Route path="/settings" component={requireAuth(AsyncSettings)}>
<Route path="/dashboard" component={Dashboard} />
<Route path="/settings" component={AsyncSettings}>
<IndexRedirect to="/settings/account" />
<Route path="account" component={AsyncAccountSettings} />
<Route path="github/repos" component={AsyncGitHubRepositoryList} />
<Route path="token" component={AsyncTokenSettings} />
</Route>
<Route path="/builds" component={requireAuth(UserBuildList)} />
<Route path="/builds" component={UserBuildList} />
<Route path="/login" component={Login} />
<Route path="/:provider/:ownerName" component={requireAuth(OwnerDetails)} />
<Route
path="/:provider/:ownerName/:repoName"
component={requireAuth(RepositoryDetails)}>
<Route path="/:provider/:ownerName" component={OwnerDetails} />
<Route path="/:provider/:ownerName/:repoName" component={RepositoryDetails}>
<IndexRoute component={RepositoryOverview} />
<Route path="builds" component={RepositoryBuildList} />
<Route path="change-requests" component={RepositoryChangeRequestList} />
Expand Down
6 changes: 3 additions & 3 deletions webapp/utils/requireAuth.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function(ComposedComponent) {

static contextTypes = {router: PropTypes.object.isRequired};

componentWillMount() {
componentDidMount() {
if (this.props.isAuthenticated === false) {
this.context.router.push({
pathname: '/login',
Expand All @@ -20,8 +20,8 @@ export default function(ComposedComponent) {
}
}

componentWillUpdate(nextProps) {
if (nextProps.isAuthenticated === false) {
componentDidUpdate() {
if (this.props.isAuthenticated === false) {
this.context.router.push({
pathname: '/login',
query: {next: this.buildUrl()}
Expand Down
Loading

0 comments on commit 2a30a03

Please sign in to comment.