settings.tsx 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import isEqual from 'lodash/isEqual';
  2. import Form from 'sentry/components/deprecatedforms/form';
  3. import FormState from 'sentry/components/forms/state';
  4. import LoadingIndicator from 'sentry/components/loadingIndicator';
  5. import DefaultSettings from 'sentry/plugins/components/settings';
  6. type Props = DefaultSettings['props'];
  7. type State = DefaultSettings['state'] & {
  8. // NB: "On-premises" here refers to on-premises SessionStack, not Sentry.
  9. // That said, we only support connecting to an on-premises SessionStack from
  10. // a self-hosted Sentry: https://docs.sessionstack.com/docs/sentry.
  11. showOnPremisesConfiguration?: boolean;
  12. };
  13. class Settings extends DefaultSettings<Props, State> {
  14. REQUIRED_FIELDS = ['account_email', 'api_token', 'website_id'];
  15. ON_PREMISES_FIELDS = ['api_url', 'player_url'];
  16. renderFields(fields: State['fieldList']) {
  17. return fields?.map(f =>
  18. this.renderField({
  19. config: f,
  20. formData: this.state.formData,
  21. formErrors: this.state.errors,
  22. onChange: this.changeField.bind(this, f.name),
  23. })
  24. );
  25. }
  26. filterFields(fields: State['fieldList'], fieldNames: string[]) {
  27. return fields?.filter(field => fieldNames.includes(field.name)) ?? [];
  28. }
  29. toggleOnPremisesConfiguration = () => {
  30. this.setState({
  31. showOnPremisesConfiguration: !this.state.showOnPremisesConfiguration,
  32. });
  33. };
  34. render() {
  35. if (this.state.state === FormState.LOADING) {
  36. return <LoadingIndicator />;
  37. }
  38. if (this.state.state === FormState.ERROR && !this.state.fieldList) {
  39. return (
  40. <div className="alert alert-error m-b-1">
  41. An unknown error occurred. Need help with this?{' '}
  42. <a href="https://sentry.io/support/">Contact support</a>
  43. </div>
  44. );
  45. }
  46. const isSaving = this.state.state === FormState.SAVING;
  47. const hasChanges = !isEqual(this.state.initialData, this.state.formData);
  48. const requiredFields = this.filterFields(this.state.fieldList, this.REQUIRED_FIELDS);
  49. const onPremisesFields = this.filterFields(
  50. this.state.fieldList,
  51. this.ON_PREMISES_FIELDS
  52. );
  53. return (
  54. <Form onSubmit={this.onSubmit} submitDisabled={isSaving || !hasChanges}>
  55. {this.state.errors.__all__ && (
  56. <div className="alert alert-block alert-error">
  57. <ul>
  58. <li>{this.state.errors.__all__}</li>
  59. </ul>
  60. </div>
  61. )}
  62. {this.renderFields(requiredFields)}
  63. {onPremisesFields.length > 0 ? (
  64. <div className="control-group">
  65. <button
  66. className="btn btn-default"
  67. type="button"
  68. onClick={this.toggleOnPremisesConfiguration}
  69. >
  70. Configure on-premises
  71. </button>
  72. </div>
  73. ) : null}
  74. {this.state.showOnPremisesConfiguration
  75. ? this.renderFields(onPremisesFields)
  76. : null}
  77. </Form>
  78. );
  79. }
  80. }
  81. export default Settings;