|
@@ -1,22 +1,27 @@
|
|
-import React, { useCallback, useRef } from 'react';
|
|
|
|
|
|
+import React from 'react';
|
|
import { FormError } from 'components/common/Input/Input.styled';
|
|
import { FormError } from 'components/common/Input/Input.styled';
|
|
import { ErrorMessage } from '@hookform/error-message';
|
|
import { ErrorMessage } from '@hookform/error-message';
|
|
-import { useForm, Controller, useFieldArray } from 'react-hook-form';
|
|
|
|
|
|
+import {
|
|
|
|
+ useForm,
|
|
|
|
+ Controller,
|
|
|
|
+ useFieldArray,
|
|
|
|
+ FormProvider,
|
|
|
|
+} from 'react-hook-form';
|
|
import { Button } from 'components/common/Button/Button';
|
|
import { Button } from 'components/common/Button/Button';
|
|
import IconButtonWrapper from 'components/common/Icons/IconButtonWrapper';
|
|
import IconButtonWrapper from 'components/common/Icons/IconButtonWrapper';
|
|
import CloseIcon from 'components/common/Icons/CloseIcon';
|
|
import CloseIcon from 'components/common/Icons/CloseIcon';
|
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
import { yupResolver } from '@hookform/resolvers/yup';
|
|
import yup from 'lib/yupExtended';
|
|
import yup from 'lib/yupExtended';
|
|
import PlusIcon from 'components/common/Icons/PlusIcon';
|
|
import PlusIcon from 'components/common/Icons/PlusIcon';
|
|
-import ReactAce from 'react-ace/lib/ace';
|
|
|
|
|
|
+import ReactAce from 'react-ace';
|
|
|
|
+import Input from 'components/common/Input/Input';
|
|
|
|
|
|
import * as S from './QueryForm.styled';
|
|
import * as S from './QueryForm.styled';
|
|
|
|
|
|
-export interface Props {
|
|
|
|
|
|
+interface QueryFormProps {
|
|
fetching: boolean;
|
|
fetching: boolean;
|
|
hasResults: boolean;
|
|
hasResults: boolean;
|
|
- handleClearResults: () => void;
|
|
|
|
- handleSSECancel: () => void;
|
|
|
|
|
|
+ resetResults: () => void;
|
|
submitHandler: (values: FormValues) => void;
|
|
submitHandler: (values: FormValues) => void;
|
|
}
|
|
}
|
|
type StreamsPropertiesType = {
|
|
type StreamsPropertiesType = {
|
|
@@ -37,20 +42,13 @@ const validationSchema = yup.object({
|
|
streamsProperties: yup.array().of(streamsPropertiesSchema),
|
|
streamsProperties: yup.array().of(streamsPropertiesSchema),
|
|
});
|
|
});
|
|
|
|
|
|
-const QueryForm: React.FC<Props> = ({
|
|
|
|
|
|
+const QueryForm: React.FC<QueryFormProps> = ({
|
|
fetching,
|
|
fetching,
|
|
hasResults,
|
|
hasResults,
|
|
- handleClearResults,
|
|
|
|
- handleSSECancel,
|
|
|
|
submitHandler,
|
|
submitHandler,
|
|
|
|
+ resetResults,
|
|
}) => {
|
|
}) => {
|
|
- const {
|
|
|
|
- handleSubmit,
|
|
|
|
- setValue,
|
|
|
|
- getValues,
|
|
|
|
- control,
|
|
|
|
- formState: { errors },
|
|
|
|
- } = useForm<FormValues>({
|
|
|
|
|
|
+ const methods = useForm<FormValues>({
|
|
mode: 'onTouched',
|
|
mode: 'onTouched',
|
|
resolver: yupResolver(validationSchema),
|
|
resolver: yupResolver(validationSchema),
|
|
defaultValues: {
|
|
defaultValues: {
|
|
@@ -58,7 +56,16 @@ const QueryForm: React.FC<Props> = ({
|
|
streamsProperties: [{ key: '', value: '' }],
|
|
streamsProperties: [{ key: '', value: '' }],
|
|
},
|
|
},
|
|
});
|
|
});
|
|
- const { fields, append, remove } = useFieldArray<
|
|
|
|
|
|
+
|
|
|
|
+ const {
|
|
|
|
+ handleSubmit,
|
|
|
|
+ setValue,
|
|
|
|
+ control,
|
|
|
|
+ watch,
|
|
|
|
+ formState: { errors, isDirty },
|
|
|
|
+ } = methods;
|
|
|
|
+
|
|
|
|
+ const { fields, append, remove, update } = useFieldArray<
|
|
FormValues,
|
|
FormValues,
|
|
'streamsProperties'
|
|
'streamsProperties'
|
|
>({
|
|
>({
|
|
@@ -66,17 +73,24 @@ const QueryForm: React.FC<Props> = ({
|
|
name: 'streamsProperties',
|
|
name: 'streamsProperties',
|
|
});
|
|
});
|
|
|
|
|
|
- const handleAddNewProperty = useCallback(() => {
|
|
|
|
- if (
|
|
|
|
- getValues().streamsProperties.every((prop) => {
|
|
|
|
- return prop.key;
|
|
|
|
- })
|
|
|
|
- ) {
|
|
|
|
- append({ key: '', value: '' });
|
|
|
|
|
|
+ const watchStreamProps = watch('streamsProperties');
|
|
|
|
+
|
|
|
|
+ const appendProperty = () => {
|
|
|
|
+ append({ key: '', value: '' });
|
|
|
|
+ };
|
|
|
|
+ const removeProperty = (index: number) => () => {
|
|
|
|
+ if (fields.length === 1) {
|
|
|
|
+ update(index, { key: '', value: '' });
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- }, []);
|
|
|
|
|
|
|
|
- const inputRef = useRef<ReactAce>(null);
|
|
|
|
|
|
+ remove(index);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const isAppendDisabled =
|
|
|
|
+ fetching || !!watchStreamProps.find((field) => !field.key);
|
|
|
|
+
|
|
|
|
+ const inputRef = React.useRef<ReactAce>(null);
|
|
|
|
|
|
const handleFocus = () => {
|
|
const handleFocus = () => {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -87,145 +101,117 @@ const QueryForm: React.FC<Props> = ({
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ const handleClear = () => {
|
|
|
|
+ handleFocus();
|
|
|
|
+ resetResults();
|
|
|
|
+ };
|
|
|
|
+
|
|
return (
|
|
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)();
|
|
|
|
|
|
+ <FormProvider {...methods}>
|
|
|
|
+ <S.QueryWrapper>
|
|
|
|
+ <form onSubmit={handleSubmit(submitHandler)}>
|
|
|
|
+ <S.KSQLInputsWrapper>
|
|
|
|
+ <S.Fieldset>
|
|
|
|
+ <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}
|
|
|
|
|
|
+ ]}
|
|
|
|
+ readOnly={fetching}
|
|
|
|
+ ref={inputRef}
|
|
|
|
+ />
|
|
|
|
+ )}
|
|
|
|
+ />
|
|
|
|
+ <FormError>
|
|
|
|
+ <ErrorMessage errors={errors} name="ksql" />
|
|
|
|
+ </FormError>
|
|
|
|
+ </S.Fieldset>
|
|
|
|
+
|
|
|
|
+ <S.Fieldset>
|
|
|
|
+ Stream properties:
|
|
|
|
+ {fields.map((field, index) => (
|
|
|
|
+ <S.InputsContainer key={field.id}>
|
|
|
|
+ <Input
|
|
name={`streamsProperties.${index}.key`}
|
|
name={`streamsProperties.${index}.key`}
|
|
- render={({ field }) => (
|
|
|
|
- <input
|
|
|
|
- {...field}
|
|
|
|
- placeholder="Key"
|
|
|
|
- aria-label="key"
|
|
|
|
- type="text"
|
|
|
|
- autoComplete="off"
|
|
|
|
- />
|
|
|
|
- )}
|
|
|
|
|
|
+ placeholder="Key"
|
|
|
|
+ type="text"
|
|
|
|
+ autoComplete="off"
|
|
|
|
+ withError
|
|
/>
|
|
/>
|
|
- <FormError>
|
|
|
|
- <ErrorMessage
|
|
|
|
- errors={errors}
|
|
|
|
- name={`streamsProperties.${index}.key`}
|
|
|
|
- />
|
|
|
|
- </FormError>
|
|
|
|
- </S.StreamPropertiesInputWrapper>
|
|
|
|
- <S.StreamPropertiesInputWrapper>
|
|
|
|
- <Controller
|
|
|
|
- control={control}
|
|
|
|
|
|
+ <Input
|
|
name={`streamsProperties.${index}.value`}
|
|
name={`streamsProperties.${index}.value`}
|
|
- render={({ field }) => (
|
|
|
|
- <input
|
|
|
|
- {...field}
|
|
|
|
- placeholder="Value"
|
|
|
|
- aria-label="value"
|
|
|
|
- type="text"
|
|
|
|
- autoComplete="off"
|
|
|
|
- />
|
|
|
|
- )}
|
|
|
|
|
|
+ placeholder="Value"
|
|
|
|
+ type="text"
|
|
|
|
+ autoComplete="off"
|
|
|
|
+ withError
|
|
/>
|
|
/>
|
|
- <FormError>
|
|
|
|
- <ErrorMessage
|
|
|
|
- errors={errors}
|
|
|
|
- name={`streamsProperties.${index}.value`}
|
|
|
|
- />
|
|
|
|
- </FormError>
|
|
|
|
- </S.StreamPropertiesInputWrapper>
|
|
|
|
-
|
|
|
|
- <S.DeleteButtonWrapper onClick={() => remove(index)}>
|
|
|
|
- <IconButtonWrapper aria-label="deleteProperty">
|
|
|
|
|
|
+ <IconButtonWrapper
|
|
|
|
+ aria-label="deleteProperty"
|
|
|
|
+ onClick={removeProperty(index)}
|
|
|
|
+ >
|
|
<CloseIcon aria-hidden />
|
|
<CloseIcon aria-hidden />
|
|
</IconButtonWrapper>
|
|
</IconButtonWrapper>
|
|
- </S.DeleteButtonWrapper>
|
|
|
|
- </S.InputsContainer>
|
|
|
|
- ))}
|
|
|
|
|
|
+ </S.InputsContainer>
|
|
|
|
+ ))}
|
|
|
|
+ <Button
|
|
|
|
+ type="button"
|
|
|
|
+ buttonSize="M"
|
|
|
|
+ buttonType="secondary"
|
|
|
|
+ disabled={isAppendDisabled}
|
|
|
|
+ onClick={appendProperty}
|
|
|
|
+ >
|
|
|
|
+ <PlusIcon />
|
|
|
|
+ Add Stream Property
|
|
|
|
+ </Button>
|
|
|
|
+ </S.Fieldset>
|
|
|
|
+ </S.KSQLInputsWrapper>
|
|
|
|
+ <S.ButtonsContainer>
|
|
<Button
|
|
<Button
|
|
- type="button"
|
|
|
|
- buttonSize="M"
|
|
|
|
buttonType="secondary"
|
|
buttonType="secondary"
|
|
- onClick={handleAddNewProperty}
|
|
|
|
|
|
+ buttonSize="M"
|
|
|
|
+ disabled={fetching || !isDirty || !hasResults}
|
|
|
|
+ onClick={handleClear}
|
|
|
|
+ >
|
|
|
|
+ Clear results
|
|
|
|
+ </Button>
|
|
|
|
+ <Button
|
|
|
|
+ buttonType="primary"
|
|
|
|
+ buttonSize="M"
|
|
|
|
+ type="submit"
|
|
|
|
+ disabled={fetching}
|
|
|
|
+ onClick={handleFocus}
|
|
>
|
|
>
|
|
- <PlusIcon />
|
|
|
|
- Add Stream Property
|
|
|
|
|
|
+ Execute
|
|
</Button>
|
|
</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>
|
|
|
|
|
|
+ </S.ButtonsContainer>
|
|
|
|
+ </form>
|
|
|
|
+ </S.QueryWrapper>
|
|
|
|
+ </FormProvider>
|
|
);
|
|
);
|
|
};
|
|
};
|
|
|
|
|