withRepositories.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import * as React from 'react';
  2. import {getRepositories} from 'sentry/actionCreators/repositories';
  3. import RepositoryActions from 'sentry/actions/repositoryActions';
  4. import {Client} from 'sentry/api';
  5. import RepositoryStore from 'sentry/stores/repositoryStore';
  6. import {Organization, Repository} from 'sentry/types';
  7. import getDisplayName from 'sentry/utils/getDisplayName';
  8. type DependentProps = {
  9. api: Client;
  10. organization: Organization;
  11. };
  12. type InjectedProps = {
  13. repositories?: Repository[];
  14. repositoriesError?: Error;
  15. repositoriesLoading?: boolean;
  16. };
  17. const INITIAL_STATE: InjectedProps = {
  18. repositories: undefined,
  19. repositoriesLoading: undefined,
  20. repositoriesError: undefined,
  21. };
  22. function withRepositories<P extends DependentProps>(
  23. WrappedComponent: React.ComponentType<P>
  24. ) {
  25. class WithRepositories extends React.Component<P & DependentProps, InjectedProps> {
  26. static displayName = `withRepositories(${getDisplayName(WrappedComponent)})`;
  27. constructor(props: P & DependentProps, context: any) {
  28. super(props, context);
  29. const {organization} = this.props;
  30. const orgSlug = organization.slug;
  31. const repoData = RepositoryStore.get();
  32. if (repoData.orgSlug !== orgSlug) {
  33. RepositoryActions.resetRepositories();
  34. }
  35. this.state =
  36. repoData.orgSlug === orgSlug
  37. ? {...INITIAL_STATE, ...repoData}
  38. : {...INITIAL_STATE};
  39. }
  40. componentDidMount() {
  41. // XXX(leedongwei): Do not move this function call unless you modify the
  42. // unit test named "prevents repeated calls"
  43. this.fetchRepositories();
  44. }
  45. componentWillUnmount() {
  46. this.unsubscribe();
  47. }
  48. unsubscribe = RepositoryStore.listen(() => this.onStoreUpdate(), undefined);
  49. fetchRepositories() {
  50. const {api, organization} = this.props;
  51. const orgSlug = organization.slug;
  52. const repoData = RepositoryStore.get();
  53. // XXX(leedongwei): Do not check the orgSlug here. It would have been
  54. // verified at `getInitialState`. The short-circuit hack in actionCreator
  55. // does not update the orgSlug in the store.
  56. if (
  57. (!repoData.repositories && !repoData.repositoriesLoading) ||
  58. repoData.repositoriesError
  59. ) {
  60. getRepositories(api, {orgSlug});
  61. }
  62. }
  63. onStoreUpdate() {
  64. const repoData = RepositoryStore.get();
  65. this.setState({...repoData});
  66. }
  67. render() {
  68. return <WrappedComponent {...this.props} {...this.state} />;
  69. }
  70. }
  71. return WithRepositories;
  72. }
  73. export default withRepositories;