customResolutionModal.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import * as React from 'react';
  2. import {components as selectComponents} from 'react-select';
  3. import {ModalRenderProps} from 'app/actionCreators/modal';
  4. import Button from 'app/components/button';
  5. import {SelectAsyncField} from 'app/components/forms';
  6. import TimeSince from 'app/components/timeSince';
  7. import Version from 'app/components/version';
  8. import {t} from 'app/locale';
  9. import space from 'app/styles/space';
  10. import {Release} from 'app/types';
  11. type Props = ModalRenderProps & {
  12. onSelected: ({inRelease: string}) => void;
  13. orgSlug: string;
  14. projectSlug?: string;
  15. };
  16. type State = {
  17. version: string;
  18. };
  19. function VersionOption({
  20. data,
  21. ...props
  22. }: React.ComponentProps<typeof selectComponents.Option>) {
  23. const release = data.release as Release;
  24. return (
  25. <selectComponents.Option data={data} {...props}>
  26. <strong>
  27. <Version version={release.version} anchor={false} />
  28. </strong>
  29. <br />
  30. <small>
  31. {t('Created')} <TimeSince date={release.dateCreated} />
  32. </small>
  33. </selectComponents.Option>
  34. );
  35. }
  36. class CustomResolutionModal extends React.Component<Props, State> {
  37. state: State = {
  38. version: '',
  39. };
  40. onChange = (value: string | number | boolean) => {
  41. this.setState({version: value as string}); // TODO(ts): Add select value type as generic to select controls
  42. };
  43. onAsyncFieldResults = (results: Release[]) =>
  44. results.map(release => ({
  45. value: release.version,
  46. label: release.version,
  47. release,
  48. }));
  49. render() {
  50. const {orgSlug, projectSlug, closeModal, onSelected, Header, Body, Footer} =
  51. this.props;
  52. const url = projectSlug
  53. ? `/projects/${orgSlug}/${projectSlug}/releases/`
  54. : `/organizations/${orgSlug}/releases/`;
  55. const onSubmit = (e: React.FormEvent) => {
  56. e.preventDefault();
  57. onSelected({inRelease: this.state.version});
  58. closeModal();
  59. };
  60. return (
  61. <form onSubmit={onSubmit}>
  62. <Header>{t('Resolved In')}</Header>
  63. <Body>
  64. <SelectAsyncField
  65. label={t('Version')}
  66. id="version"
  67. name="version"
  68. onChange={this.onChange}
  69. placeholder={t('e.g. 1.0.4')}
  70. url={url}
  71. onResults={this.onAsyncFieldResults}
  72. onQuery={query => ({query})}
  73. components={{
  74. Option: VersionOption,
  75. }}
  76. />
  77. </Body>
  78. <Footer>
  79. <Button type="button" css={{marginRight: space(1.5)}} onClick={closeModal}>
  80. {t('Cancel')}
  81. </Button>
  82. <Button type="submit" priority="primary">
  83. {t('Save Changes')}
  84. </Button>
  85. </Footer>
  86. </form>
  87. );
  88. }
  89. }
  90. export default CustomResolutionModal;