queryField.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import {Fragment, type ReactNode} from 'react';
  2. import type {DraggableSyntheticListeners, UseDraggableArguments} from '@dnd-kit/core';
  3. import styled from '@emotion/styled';
  4. import {Button} from 'sentry/components/button';
  5. import {IconDelete, IconGrabbable} from 'sentry/icons';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import type {QueryFieldValue} from 'sentry/utils/discover/fields';
  9. import {QueryField as TableQueryField} from 'sentry/views/discover/table/queryField';
  10. import {FieldValueKind} from 'sentry/views/discover/table/types';
  11. export interface QueryFieldProps {
  12. fieldOptions: React.ComponentProps<typeof TableQueryField>['fieldOptions'];
  13. onChange: (newValue: QueryFieldValue) => void;
  14. value: QueryFieldValue;
  15. attributes?: UseDraggableArguments['attributes'];
  16. canDelete?: boolean;
  17. canDrag?: boolean;
  18. fieldValidationError?: ReactNode;
  19. forwardRef?: React.Ref<HTMLDivElement>;
  20. isDragging?: boolean;
  21. listeners?: DraggableSyntheticListeners;
  22. onDelete?: () => void;
  23. style?: React.CSSProperties;
  24. }
  25. export function QueryField({
  26. onDelete,
  27. onChange,
  28. fieldOptions,
  29. value,
  30. forwardRef,
  31. listeners,
  32. attributes,
  33. canDelete,
  34. canDrag,
  35. style,
  36. fieldValidationError,
  37. isDragging,
  38. }: QueryFieldProps) {
  39. return (
  40. <QueryFieldWrapper ref={forwardRef} style={style}>
  41. {isDragging ? null : (
  42. <Fragment>
  43. {canDrag && (
  44. <DragAndReorderButton
  45. {...listeners}
  46. {...attributes}
  47. aria-label={t('Drag to reorder')}
  48. icon={<IconGrabbable size="xs" />}
  49. size="zero"
  50. borderless
  51. />
  52. )}
  53. <TableQueryField
  54. placeholder={t('Select group')}
  55. fieldValue={value}
  56. fieldOptions={fieldOptions}
  57. onChange={onChange}
  58. filterPrimaryOptions={option => option.value.kind !== FieldValueKind.FUNCTION}
  59. />
  60. {fieldValidationError ? fieldValidationError : null}
  61. {canDelete && (
  62. <Button
  63. size="zero"
  64. borderless
  65. onClick={onDelete}
  66. icon={<IconDelete />}
  67. title={t('Remove group')}
  68. aria-label={t('Remove group')}
  69. />
  70. )}
  71. </Fragment>
  72. )}
  73. </QueryFieldWrapper>
  74. );
  75. }
  76. const DragAndReorderButton = styled(Button)`
  77. height: ${p => p.theme.form.md.height}px;
  78. `;
  79. const QueryFieldWrapper = styled('div')`
  80. display: flex;
  81. align-items: center;
  82. justify-content: space-between;
  83. width: 100%;
  84. > * + * {
  85. margin-left: ${space(1)};
  86. }
  87. `;