withRepositories.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import {Component} from 'react';
  2. import {getRepositories} from 'sentry/actionCreators/repositories';
  3. import {Client} from 'sentry/api';
  4. import RepositoryStore from 'sentry/stores/repositoryStore';
  5. import {Organization, Repository} from 'sentry/types';
  6. import getDisplayName from 'sentry/utils/getDisplayName';
  7. type DependentProps = {
  8. api: Client;
  9. organization: Organization;
  10. };
  11. type InjectedProps = {
  12. repositories?: Repository[];
  13. repositoriesError?: Error;
  14. repositoriesLoading?: boolean;
  15. };
  16. const INITIAL_STATE: InjectedProps = {
  17. repositories: undefined,
  18. repositoriesLoading: undefined,
  19. repositoriesError: undefined,
  20. };
  21. function withRepositories<P extends DependentProps>(
  22. WrappedComponent: React.ComponentType<P>
  23. ) {
  24. class WithRepositories extends Component<P & DependentProps, InjectedProps> {
  25. static displayName = `withRepositories(${getDisplayName(WrappedComponent)})`;
  26. constructor(props: P & DependentProps, context: any) {
  27. super(props, context);
  28. const repoData = RepositoryStore.get();
  29. this.state =
  30. repoData.orgSlug === props.organization.slug
  31. ? {...INITIAL_STATE, ...repoData}
  32. : {...INITIAL_STATE};
  33. }
  34. componentDidMount() {
  35. const {organization} = this.props;
  36. const orgSlug = organization.slug;
  37. const repoData = RepositoryStore.get();
  38. if (repoData.orgSlug !== orgSlug) {
  39. RepositoryStore.resetRepositories();
  40. }
  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;