indicators.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import React from 'react';
  2. import {ThemeProvider} from '@emotion/react';
  3. import styled from '@emotion/styled';
  4. import createReactClass from 'create-react-class';
  5. import {AnimatePresence} from 'framer-motion';
  6. import Reflux from 'reflux';
  7. import {Indicator, removeIndicator} from 'app/actionCreators/indicator';
  8. import ToastIndicator from 'app/components/alerts/toastIndicator';
  9. import IndicatorStore from 'app/stores/indicatorStore';
  10. import {lightTheme} from 'app/utils/theme';
  11. const Toasts = styled('div')`
  12. position: fixed;
  13. right: 30px;
  14. bottom: 30px;
  15. z-index: ${p => p.theme.zIndex.toast};
  16. `;
  17. type Props = {
  18. items: Indicator[];
  19. className?: string;
  20. };
  21. class Indicators extends React.Component<Props> {
  22. static defaultProps = {
  23. items: [],
  24. };
  25. handleDismiss = (indicator: Indicator) => {
  26. removeIndicator(indicator);
  27. };
  28. render() {
  29. const {items, ...props} = this.props;
  30. return (
  31. <Toasts {...props}>
  32. <AnimatePresence>
  33. {items.map((indicator, i) => (
  34. // We purposefully use `i` as key here because of transitions
  35. // Toasts can now queue up, so when we change from [firstToast] -> [secondToast],
  36. // we don't want to animate `firstToast` out and `secondToast` in, rather we want
  37. // to replace `firstToast` with `secondToast`
  38. <ToastIndicator
  39. onDismiss={this.handleDismiss}
  40. indicator={indicator}
  41. key={i}
  42. />
  43. ))}
  44. </AnimatePresence>
  45. </Toasts>
  46. );
  47. }
  48. }
  49. const IndicatorsContainer = createReactClass<Omit<Props, 'items'>>({
  50. displayName: 'IndicatorsContainer',
  51. mixins: [Reflux.connect(IndicatorStore, 'items') as any],
  52. getInitialState() {
  53. return {
  54. items: [],
  55. };
  56. },
  57. render() {
  58. // #NEW-SETTINGS - remove ThemeProvider here once new settings is merged
  59. // `alerts.html` django view includes this container and doesn't have a theme provider
  60. // not even sure it is used in django views but this is just an easier temp solution
  61. return (
  62. <ThemeProvider theme={lightTheme}>
  63. <Indicators {...this.props} items={this.state.items} />
  64. </ThemeProvider>
  65. );
  66. },
  67. });
  68. export default IndicatorsContainer;
  69. export {Indicators};