123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- import React, { useCallback, useRef } from 'react';
- import { FormError } from 'components/common/Input/Input.styled';
- import { ErrorMessage } from '@hookform/error-message';
- import { useForm, Controller, useFieldArray } from 'react-hook-form';
- import { Button } from 'components/common/Button/Button';
- import IconButtonWrapper from 'components/common/Icons/IconButtonWrapper';
- import CloseIcon from 'components/common/Icons/CloseIcon';
- import { yupResolver } from '@hookform/resolvers/yup';
- import yup from 'lib/yupExtended';
- import PlusIcon from 'components/common/Icons/PlusIcon';
- import ReactAce from 'react-ace/lib/ace';
- import * as S from './QueryForm.styled';
- export interface Props {
- fetching: boolean;
- hasResults: boolean;
- handleClearResults: () => void;
- handleSSECancel: () => void;
- submitHandler: (values: FormValues) => void;
- }
- type StreamsPropertiesType = {
- key: string;
- value: string;
- };
- export type FormValues = {
- ksql: string;
- streamsProperties: StreamsPropertiesType[];
- };
- const streamsPropertiesSchema = yup.object().shape({
- key: yup.string().trim(),
- value: yup.string().trim(),
- });
- const validationSchema = yup.object({
- ksql: yup.string().trim().required(),
- streamsProperties: yup.array().of(streamsPropertiesSchema),
- });
- const QueryForm: React.FC<Props> = ({
- fetching,
- hasResults,
- handleClearResults,
- handleSSECancel,
- submitHandler,
- }) => {
- const {
- handleSubmit,
- setValue,
- getValues,
- control,
- formState: { errors },
- } = useForm<FormValues>({
- mode: 'onTouched',
- resolver: yupResolver(validationSchema),
- defaultValues: {
- ksql: '',
- streamsProperties: [{ key: '', value: '' }],
- },
- });
- const { fields, append, remove } = useFieldArray<
- FormValues,
- 'streamsProperties'
- >({
- control,
- name: 'streamsProperties',
- });
- const handleAddNewProperty = useCallback(() => {
- if (
- getValues().streamsProperties.every((prop) => {
- return prop.key;
- })
- ) {
- append({ key: '', value: '' });
- }
- }, []);
- const inputRef = useRef<ReactAce>(null);
- const handleFocus = () => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const textInput = inputRef?.current?.editor?.textInput as any;
- if (textInput) {
- textInput.focus();
- }
- };
- return (
- <S.QueryWrapper>
- <form onSubmit={handleSubmit(submitHandler)}>
- <S.KSQLInputsWrapper>
- <S.Fieldset aria-labelledby="ksqlLabel">
- <S.KSQLInputHeader>
- <label id="ksqlLabel">KSQL</label>
- <Button
- onClick={() => setValue('ksql', '')}
- buttonType="primary"
- buttonSize="S"
- isInverted
- >
- Clear
- </Button>
- </S.KSQLInputHeader>
- <Controller
- control={control}
- name="ksql"
- render={({ field }) => (
- <S.SQLEditor
- {...field}
- commands={[
- {
- // commands is array of key bindings.
- // name for the key binding.
- name: 'commandName',
- // key combination used for the command.
- bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter' },
- // function to execute when keys are pressed.
- exec: () => {
- handleSubmit(submitHandler)();
- },
- },
- ]}
- readOnly={fetching}
- ref={inputRef}
- />
- )}
- />
- <FormError>
- <ErrorMessage errors={errors} name="ksql" />
- </FormError>
- </S.Fieldset>
- <S.StreamPropertiesContainer>
- Stream properties:
- {fields.map((item, index) => (
- <S.InputsContainer key={item.id}>
- <S.StreamPropertiesInputWrapper>
- <Controller
- control={control}
- name={`streamsProperties.${index}.key`}
- render={({ field }) => (
- <input
- {...field}
- placeholder="Key"
- aria-label="key"
- type="text"
- autoComplete="off"
- />
- )}
- />
- <FormError>
- <ErrorMessage
- errors={errors}
- name={`streamsProperties.${index}.key`}
- />
- </FormError>
- </S.StreamPropertiesInputWrapper>
- <S.StreamPropertiesInputWrapper>
- <Controller
- control={control}
- name={`streamsProperties.${index}.value`}
- render={({ field }) => (
- <input
- {...field}
- placeholder="Value"
- aria-label="value"
- type="text"
- autoComplete="off"
- />
- )}
- />
- <FormError>
- <ErrorMessage
- errors={errors}
- name={`streamsProperties.${index}.value`}
- />
- </FormError>
- </S.StreamPropertiesInputWrapper>
- <S.DeleteButtonWrapper onClick={() => remove(index)}>
- <IconButtonWrapper aria-label="deleteProperty">
- <CloseIcon aria-hidden />
- </IconButtonWrapper>
- </S.DeleteButtonWrapper>
- </S.InputsContainer>
- ))}
- <Button
- type="button"
- buttonSize="M"
- buttonType="secondary"
- onClick={handleAddNewProperty}
- >
- <PlusIcon />
- Add Stream Property
- </Button>
- </S.StreamPropertiesContainer>
- </S.KSQLInputsWrapper>
- <S.KSQLButtons>
- <Button
- buttonType="primary"
- buttonSize="M"
- type="submit"
- disabled={fetching}
- onClick={handleFocus}
- >
- Execute
- </Button>
- <Button
- buttonType="secondary"
- buttonSize="M"
- disabled={!fetching}
- onClick={handleSSECancel}
- >
- Stop query
- </Button>
- <Button
- buttonType="secondary"
- buttonSize="M"
- disabled={fetching || !hasResults}
- onClick={handleClearResults}
- >
- Clear results
- </Button>
- </S.KSQLButtons>
- </form>
- </S.QueryWrapper>
- );
- };
- export default QueryForm;
|