nameAndDescFields.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import {Fragment, useState} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import TextArea from 'sentry/components/forms/controls/textarea';
  5. import TextField from 'sentry/components/forms/fields/textField';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import {trackAnalytics} from 'sentry/utils/analytics';
  9. import {WidgetBuilderVersion} from 'sentry/utils/analytics/dashboardsAnalyticsEvents';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import {SectionHeader} from 'sentry/views/dashboards/widgetBuilder/components/common/sectionHeader';
  12. import {useWidgetBuilderContext} from 'sentry/views/dashboards/widgetBuilder/contexts/widgetBuilderContext';
  13. import useDashboardWidgetSource from 'sentry/views/dashboards/widgetBuilder/hooks/useDashboardWidgetSource';
  14. import useIsEditingWidget from 'sentry/views/dashboards/widgetBuilder/hooks/useIsEditingWidget';
  15. import {BuilderStateAction} from 'sentry/views/dashboards/widgetBuilder/hooks/useWidgetBuilderState';
  16. interface WidgetBuilderNameAndDescriptionProps {
  17. error?: Record<string, any>;
  18. setError?: (error: Record<string, any>) => void;
  19. }
  20. function WidgetBuilderNameAndDescription({
  21. error,
  22. setError,
  23. }: WidgetBuilderNameAndDescriptionProps) {
  24. const organization = useOrganization();
  25. const {state, dispatch} = useWidgetBuilderContext();
  26. const [isDescSelected, setIsDescSelected] = useState(state.description ? true : false);
  27. const isEditing = useIsEditingWidget();
  28. const source = useDashboardWidgetSource();
  29. return (
  30. <Fragment>
  31. <SectionHeader title={t('Widget Name & Description')} />
  32. <StyledInput
  33. name={t('Widget Name')}
  34. size="md"
  35. placeholder={t('Name')}
  36. title={t('Widget Name')}
  37. aria-label={t('Widget Name')}
  38. value={state.title}
  39. onChange={(newTitle: any) => {
  40. // clear error once user starts typing
  41. setError?.({...error, title: undefined});
  42. dispatch({type: BuilderStateAction.SET_TITLE, payload: newTitle});
  43. }}
  44. onBlur={() => {
  45. trackAnalytics('dashboards_views.widget_builder.change', {
  46. from: source,
  47. widget_type: state.dataset ?? '',
  48. builder_version: WidgetBuilderVersion.SLIDEOUT,
  49. field: 'title',
  50. value: '',
  51. new_widget: !isEditing,
  52. organization,
  53. });
  54. }}
  55. required
  56. error={error?.title}
  57. inline={false}
  58. />
  59. {!isDescSelected && (
  60. <AddDescriptionButton
  61. priority="link"
  62. aria-label={t('Add Widget Description')}
  63. onClick={() => {
  64. setIsDescSelected(true);
  65. }}
  66. data-test-id={'add-description'}
  67. >
  68. {t('+ Add Widget Description')}
  69. </AddDescriptionButton>
  70. )}
  71. {isDescSelected && (
  72. <DescriptionTextArea
  73. placeholder={t('Description')}
  74. aria-label={t('Widget Description')}
  75. autosize
  76. rows={4}
  77. value={state.description}
  78. onChange={e => {
  79. dispatch({type: BuilderStateAction.SET_DESCRIPTION, payload: e.target.value});
  80. }}
  81. onBlur={() => {
  82. trackAnalytics('dashboards_views.widget_builder.change', {
  83. from: source,
  84. widget_type: state.dataset ?? '',
  85. builder_version: WidgetBuilderVersion.SLIDEOUT,
  86. field: 'description',
  87. value: '',
  88. new_widget: !isEditing,
  89. organization,
  90. });
  91. }}
  92. />
  93. )}
  94. </Fragment>
  95. );
  96. }
  97. export default WidgetBuilderNameAndDescription;
  98. const StyledInput = styled(TextField)`
  99. margin-bottom: ${space(1)};
  100. padding: 0;
  101. border: none;
  102. `;
  103. const AddDescriptionButton = styled(Button)`
  104. margin-bottom: ${space(1)};
  105. `;
  106. const DescriptionTextArea = styled(TextArea)`
  107. margin: ${space(2)} 0;
  108. `;