console: console support for actions response transform

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6455
Co-authored-by: Sooraj <8408875+soorajshankar@users.noreply.github.com>
GitOrigin-RevId: 82040e5a05c035f3319a94cfb6dd94acb5259505
This commit is contained in:
Varun Choudhary 2022-10-27 19:36:06 +05:30 committed by hasura-bot
parent 4589af44b4
commit bdf1aee641
10 changed files with 693 additions and 312 deletions

View File

@ -9,16 +9,20 @@ import {
KeyValuePair, KeyValuePair,
RequestTransformState, RequestTransformState,
RequestTransformStateBody, RequestTransformStateBody,
ResponseTransformState,
ResponseTransformStateBody,
TransformationType, TransformationType,
} from './stateDefaults'; } from './stateDefaults';
import RequestOptionsTransforms from './RequestOptionsTransforms'; import RequestOptionsTransforms from './RequestOptionsTransforms';
import PayloadOptionsTransforms from './PayloadOptionsTransforms'; import PayloadOptionsTransforms from './PayloadOptionsTransforms';
import SampleContextTransforms from './SampleContextTransforms'; import SampleContextTransforms from './SampleContextTransforms';
import AddIcon from '../Icons/Add'; import AddIcon from '../Icons/Add';
import ResponseTransforms from './ResponseTransform';
type ConfigureTransformationProps = { type ConfigureTransformationProps = {
transformationType: TransformationType; transformationType: TransformationType;
state: RequestTransformState; requestTransfromState: RequestTransformState;
responseTransformState?: ResponseTransformState;
resetSampleInput: () => void; resetSampleInput: () => void;
envVarsOnChange: (envVars: KeyValuePair[]) => void; envVarsOnChange: (envVars: KeyValuePair[]) => void;
sessionVarsOnChange: (sessionVars: KeyValuePair[]) => void; sessionVarsOnChange: (sessionVars: KeyValuePair[]) => void;
@ -33,11 +37,16 @@ type ConfigureTransformationProps = {
) => void; ) => void;
requestUrlTransformOnChange: (data: boolean) => void; requestUrlTransformOnChange: (data: boolean) => void;
requestPayloadTransformOnChange: (data: boolean) => void; requestPayloadTransformOnChange: (data: boolean) => void;
responsePayloadTransformOnChange?: (data: boolean) => void;
responseBodyOnChange?: (responseBody: ResponseTransformStateBody) => void;
}; };
const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({ const ConfigureTransformation: React.FC<ConfigureTransformationProps> =
props => {
const {
transformationType, transformationType,
state, requestTransfromState,
responseTransformState,
resetSampleInput, resetSampleInput,
envVarsOnChange, envVarsOnChange,
sessionVarsOnChange, sessionVarsOnChange,
@ -49,7 +58,9 @@ const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({
requestSampleInputOnChange, requestSampleInputOnChange,
requestUrlTransformOnChange, requestUrlTransformOnChange,
requestPayloadTransformOnChange, requestPayloadTransformOnChange,
}) => { responsePayloadTransformOnChange,
responseBodyOnChange,
} = props;
const { const {
envVars, envVars,
sessionVars, sessionVars,
@ -65,7 +76,7 @@ const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({
requestTransformedBody, requestTransformedBody,
isRequestUrlTransform, isRequestUrlTransform,
isRequestPayloadTransform, isRequestPayloadTransform,
} = state; } = requestTransfromState;
const [isContextAreaActive, toggleContextArea] = useState<boolean>(false); const [isContextAreaActive, toggleContextArea] = useState<boolean>(false);
@ -76,11 +87,14 @@ const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({
const requestUrlTransformText = isRequestUrlTransform const requestUrlTransformText = isRequestUrlTransform
? `Remove Request Options Transform` ? `Remove Request Options Transform`
: `Add Request Options Transform`; : `Add Request Options Transform`;
const requestPayloadTransformText = isRequestPayloadTransform const requestPayloadTransformText = isRequestPayloadTransform
? `Remove Payload Transform` ? `Remove Payload Transform`
: `Add Payload Transform`; : `Add Payload Transform`;
const responsePayloadTransformText =
responseTransformState?.isResponsePayloadTransform
? `Remove Response Transform`
: `Add Response Transform`;
return ( return (
<> <>
<h2 className="text-lg font-semibold mb-sm flex items-center"> <h2 className="text-lg font-semibold mb-sm flex items-center">
@ -131,7 +145,8 @@ const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({
Change Request Options Change Request Options
</label> </label>
<p className="text-sm text-gray-600 mb-sm"> <p className="text-sm text-gray-600 mb-sm">
Change the method and URL to adapt to your API&apos;s expected format. Change the method and URL to adapt to your API&apos;s expected
format.
</p> </p>
<Analytics <Analytics
name={ name={
@ -154,7 +169,6 @@ const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({
{requestUrlTransformText} {requestUrlTransformText}
</Button> </Button>
</Analytics> </Analytics>
{isRequestUrlTransform ? ( {isRequestUrlTransform ? (
<RequestOptionsTransforms <RequestOptionsTransforms
requestMethod={requestMethod} requestMethod={requestMethod}
@ -212,8 +226,52 @@ const ConfigureTransformation: React.FC<ConfigureTransformationProps> = ({
/> />
) : null} ) : null}
</div> </div>
{responseTransformState && responsePayloadTransformOnChange && (
<div className="mb-lg">
<label className="block text-gray-600 font-medium mb-xs">
Change Response
</label>
<p className="text-sm text-gray-600 mb-sm">
Change the incoming response to adapt to your declared types.
</p>
<Analytics
name={
isRequestPayloadTransform
? 'actions-tab-hide-response-transform-button'
: 'actions-tab-show-response-transform-button'
}
passHtmlAttributesToChildren
>
<Button
color="white"
size="sm"
data-test="toggle-response-transform"
onClick={() => {
responsePayloadTransformOnChange(
!responseTransformState.isResponsePayloadTransform
);
resetSampleInput();
}}
>
{!responseTransformState.isResponsePayloadTransform ? (
<AddIcon />
) : null}
{responsePayloadTransformText}
</Button>
</Analytics>
{responseTransformState.isResponsePayloadTransform &&
responseBodyOnChange ? (
<ResponseTransforms
requestSampleInput={responseTransformState.responseSampleInput}
requestBody={responseTransformState.responseBody}
requestBodyError={responseTransformState.responseBodyError}
requestBodyOnChange={responseBodyOnChange}
/>
) : null}
</div>
)}
</> </>
); );
}; };
export default ConfigureTransformation; export default ConfigureTransformation;

View File

@ -0,0 +1,101 @@
import React, { useRef } from 'react';
import { useDebouncedEffect } from '@/hooks/useDebounceEffect';
import CrossIcon from '../Icons/Cross';
import TemplateEditor from './CustomEditors/TemplateEditor';
import { editorDebounceTime } from './utils';
import NumberedSidebar from './CustomEditors/NumberedSidebar';
import { KeyValuePair, RequestTransformStateBody } from './stateDefaults';
import KeyValueInput from './CustomEditors/KeyValueInput';
import { isEmpty } from '../utils/jsUtils';
import { requestBodyActionState } from './requestTransformState';
type PayloadOptionsTransformsProps = {
requestBody: RequestTransformStateBody;
requestBodyError: string;
requestSampleInput: string;
requestBodyOnChange: (requestBody: RequestTransformStateBody) => void;
};
const ResponseTransforms: React.FC<PayloadOptionsTransformsProps> = ({
requestSampleInput,
requestBody,
requestBodyError,
requestBodyOnChange,
}) => {
const editorRef = useRef<any>();
const [localFormElements, setLocalFormElements] = React.useState<
KeyValuePair[]
>(requestBody.form_template ?? [{ name: '', value: '' }]);
React.useEffect(() => {
setLocalFormElements(
requestBody.form_template ?? [{ name: '', value: '' }]
);
}, [requestBody]);
useDebouncedEffect(
() => {
requestBodyOnChange({ ...requestBody, form_template: localFormElements });
},
editorDebounceTime,
[localFormElements]
);
if (editorRef?.current?.editor?.renderer?.$cursorLayer?.element?.style) {
editorRef.current.editor.renderer.$cursorLayer.element.style.display =
'none';
}
return (
<div
className="m-md pl-lg pr-sm border-l border-l-gray-400"
data-cy="Change Payload"
>
<div className="mb-md">
<NumberedSidebar
title="Configure Response Body"
description={
<span>
The template which will transform your response body into the
required specification. You can use{' '}
<code className="text-xs">&#123;&#123;$body&#125;&#125;</code> to
access the original response body
</span>
}
number="1"
/>
{requestBody.action ===
requestBodyActionState.transformApplicationJson ? (
<TemplateEditor
requestBody={requestBody}
requestBodyError={requestBodyError}
requestSampleInput={requestSampleInput}
requestBodyOnChange={requestBodyOnChange}
/>
) : null}
{requestBody.action ===
requestBodyActionState.transformFormUrlEncoded ? (
<>
{!isEmpty(requestBodyError) && (
<div className="mb-sm" data-test="transform-requestBody-error">
<CrossIcon />
<span className="text-red-500 ml-sm">{requestBodyError}</span>
</div>
)}
<div className="grid gap-3 grid-cols-3 mb-sm">
<KeyValueInput
pairs={localFormElements}
setPairs={setLocalFormElements}
testId="add-url-encoded-body"
/>
</div>
</>
) : null}
</div>
</div>
);
};
export default ResponseTransforms;

View File

@ -46,6 +46,18 @@ import {
defaultEventRequestBody, defaultEventRequestBody,
defaultEventRequestSampleInput, defaultEventRequestSampleInput,
RequestTransformStateBody, RequestTransformStateBody,
SET_RESPONSE_PAYLOAD_TRANSFORM,
SetResponsePayloadTransform,
ResponseTransformStateBody,
SET_RESPONSE_BODY,
SetResponseBody,
SET_RESPONSE_BODY_ERROR,
SetResponseBodyError,
ResponseTransformState,
ResponseTransformEvents,
SET_RESPONSE_TRANSFORM_STATE,
defaultActionResponseBody,
SetResponseTransformState,
} from './stateDefaults'; } from './stateDefaults';
import { getSessionVarsFromLS, getEnvVarsFromLS } from './utils'; import { getSessionVarsFromLS, getEnvVarsFromLS } from './utils';
@ -108,6 +120,13 @@ export const setRequestBody = (
requestBody, requestBody,
}); });
export const setResponseBody = (
responseBody: ResponseTransformStateBody
): SetResponseBody => ({
type: SET_RESPONSE_BODY,
responseBody,
});
export const setRequestBodyError = ( export const setRequestBodyError = (
requestBodyError: string requestBodyError: string
): SetRequestBodyError => ({ ): SetRequestBodyError => ({
@ -115,6 +134,13 @@ export const setRequestBodyError = (
requestBodyError, requestBodyError,
}); });
export const setResponseBodyError = (
responseBodyError: string
): SetResponseBodyError => ({
type: SET_RESPONSE_BODY_ERROR,
responseBodyError,
});
export const setRequestSampleInput = ( export const setRequestSampleInput = (
requestSampleInput: string requestSampleInput: string
): SetRequestSampleInput => ({ ): SetRequestSampleInput => ({
@ -150,6 +176,13 @@ export const setRequestPayloadTransform = (
isRequestPayloadTransform, isRequestPayloadTransform,
}); });
export const setResponsePayloadTransform = (
isResponsePayloadTransform: boolean
): SetResponsePayloadTransform => ({
type: SET_RESPONSE_PAYLOAD_TRANSFORM,
isResponsePayloadTransform,
});
export const setRequestTransformState = ( export const setRequestTransformState = (
newState: RequestTransformState newState: RequestTransformState
): SetRequestTransformState => ({ ): SetRequestTransformState => ({
@ -157,6 +190,13 @@ export const setRequestTransformState = (
newState, newState,
}); });
export const setResponseTransformState = (
newState: ResponseTransformState
): SetResponseTransformState => ({
type: SET_RESPONSE_TRANSFORM_STATE,
newState,
});
const currentVersion = 2; const currentVersion = 2;
export const requestBodyActionState = { export const requestBodyActionState = {
@ -166,6 +206,10 @@ export const requestBodyActionState = {
'x_www_form_urlencoded' as RequestTransformBodyActions, 'x_www_form_urlencoded' as RequestTransformBodyActions,
}; };
export const responseBodyActionState = {
transformApplicationJson: 'transform' as RequestTransformBodyActions,
};
export const requestTransformState: RequestTransformState = { export const requestTransformState: RequestTransformState = {
version: currentVersion, version: currentVersion,
envVars: [], envVars: [],
@ -186,6 +230,15 @@ export const requestTransformState: RequestTransformState = {
templatingEngine: 'Kriti', templatingEngine: 'Kriti',
}; };
export const responseTransformState: ResponseTransformState = {
version: currentVersion,
isResponsePayloadTransform: false,
responseSampleInput: '',
responseBody: { action: responseBodyActionState.transformApplicationJson },
responseBodyError: '',
templatingEngine: 'Kriti',
};
export const getActionRequestTransformDefaultState = export const getActionRequestTransformDefaultState =
(): RequestTransformState => { (): RequestTransformState => {
return { return {
@ -203,6 +256,19 @@ export const getActionRequestTransformDefaultState =
}; };
}; };
export const getActionResponseTransformDefaultState =
(): ResponseTransformState => {
return {
...responseTransformState,
responseBody: {
action: responseBodyActionState.transformApplicationJson,
template: defaultActionResponseBody,
form_template: [{ name: 'name', value: '{{$body.action.name}}' }],
},
responseSampleInput: defaultActionRequestSampleInput,
};
};
export const getEventRequestTransformDefaultState = export const getEventRequestTransformDefaultState =
(): RequestTransformState => { (): RequestTransformState => {
return { return {
@ -311,3 +377,32 @@ export const requestTransformReducer = (
return state; return state;
} }
}; };
export const responseTransformReducer = (
state = responseTransformState,
action: ResponseTransformEvents
): ResponseTransformState => {
switch (action.type) {
case SET_RESPONSE_BODY:
return {
...state,
responseBody: action.responseBody,
};
case SET_RESPONSE_BODY_ERROR:
return {
...state,
responseBodyError: action.responseBodyError,
};
case SET_RESPONSE_PAYLOAD_TRANSFORM:
return {
...state,
isResponsePayloadTransform: action.isResponsePayloadTransform,
};
case SET_RESPONSE_TRANSFORM_STATE:
return {
...action.newState,
};
default:
return state;
}
};

View File

@ -10,6 +10,7 @@ import {
RequestTransformContentType, RequestTransformContentType,
RequestTransformTemplateEngine, RequestTransformTemplateEngine,
RequestTransformBody, RequestTransformBody,
ResponseTransformBody,
} from '../../../metadata/types'; } from '../../../metadata/types';
import { Nullable } from '../utils/tsUtils'; import { Nullable } from '../utils/tsUtils';
@ -40,6 +41,13 @@ export const SET_REQUEST_PAYLOAD_TRANSFORM =
'RequestTransform/SET_REQUEST_PAYLOAD_TRANSFORM'; 'RequestTransform/SET_REQUEST_PAYLOAD_TRANSFORM';
export const SET_REQUEST_TRANSFORM_STATE = export const SET_REQUEST_TRANSFORM_STATE =
'RequestTransform/SET_REQUEST_TRANSFORM_STATE'; 'RequestTransform/SET_REQUEST_TRANSFORM_STATE';
export const SET_RESPONSE_BODY = 'ResponseTransform/SET_RESPONSE_BODY';
export const SET_RESPONSE_BODY_ERROR =
'ResponseTransform/SET_RESPONSE_BODY_ERROR';
export const SET_RESPONSE_PAYLOAD_TRANSFORM =
'ResponseTransform/SET_RESPONSE_PAYLOAD_TRANSFORM';
export const SET_RESPONSE_TRANSFORM_STATE =
'RequestTransform/SET_REQUEST_TRANSFORM_STATE';
export interface SetEnvVars extends ReduxAction { export interface SetEnvVars extends ReduxAction {
type: typeof SET_ENV_VARS; type: typeof SET_ENV_VARS;
@ -86,11 +94,21 @@ export interface SetRequestBody extends ReduxAction {
requestBody: RequestTransformStateBody; requestBody: RequestTransformStateBody;
} }
export interface SetResponseBody extends ReduxAction {
type: typeof SET_RESPONSE_BODY;
responseBody: ResponseTransformStateBody;
}
export interface SetRequestBodyError extends ReduxAction { export interface SetRequestBodyError extends ReduxAction {
type: typeof SET_REQUEST_BODY_ERROR; type: typeof SET_REQUEST_BODY_ERROR;
requestBodyError: string; requestBodyError: string;
} }
export interface SetResponseBodyError extends ReduxAction {
type: typeof SET_RESPONSE_BODY_ERROR;
responseBodyError: string;
}
export interface SetRequestSampleInput extends ReduxAction { export interface SetRequestSampleInput extends ReduxAction {
type: typeof SET_REQUEST_SAMPLE_INPUT; type: typeof SET_REQUEST_SAMPLE_INPUT;
requestSampleInput: string; requestSampleInput: string;
@ -116,11 +134,21 @@ export interface SetRequestPayloadTransform extends ReduxAction {
isRequestPayloadTransform: boolean; isRequestPayloadTransform: boolean;
} }
export interface SetResponsePayloadTransform extends ReduxAction {
type: typeof SET_RESPONSE_PAYLOAD_TRANSFORM;
isResponsePayloadTransform: boolean;
}
export interface SetRequestTransformState extends ReduxAction { export interface SetRequestTransformState extends ReduxAction {
type: typeof SET_REQUEST_TRANSFORM_STATE; type: typeof SET_REQUEST_TRANSFORM_STATE;
newState: RequestTransformState; newState: RequestTransformState;
} }
export interface SetResponseTransformState extends ReduxAction {
type: typeof SET_RESPONSE_TRANSFORM_STATE;
newState: ResponseTransformState;
}
export type RequestTransformEvents = export type RequestTransformEvents =
| SetEnvVars | SetEnvVars
| SetSessionVars | SetSessionVars
@ -139,6 +167,12 @@ export type RequestTransformEvents =
| SetRequestPayloadTransform | SetRequestPayloadTransform
| SetRequestTransformState; | SetRequestTransformState;
export type ResponseTransformEvents =
| SetResponseBody
| SetResponseBodyError
| SetResponsePayloadTransform
| SetResponseTransformState;
export type RequestTransformState = { export type RequestTransformState = {
version: 1 | 2; version: 1 | 2;
envVars: KeyValuePair[]; envVars: KeyValuePair[];
@ -161,8 +195,11 @@ export type RequestTransformState = {
export type ResponseTransformState = { export type ResponseTransformState = {
version: 1 | 2; version: 1 | 2;
requestBody: RequestTransformStateBody;
templatingEngine: RequestTransformTemplateEngine; templatingEngine: RequestTransformTemplateEngine;
isResponsePayloadTransform: boolean;
responseSampleInput: string;
responseBody: ResponseTransformStateBody;
responseBodyError: string;
}; };
export type RequestTransformStateBody = Omit< export type RequestTransformStateBody = Omit<
@ -170,6 +207,11 @@ export type RequestTransformStateBody = Omit<
'form_template' 'form_template'
> & { form_template?: KeyValuePair[] }; > & { form_template?: KeyValuePair[] };
export type ResponseTransformStateBody = Omit<
ResponseTransformBody,
'form_template'
> & { form_template?: KeyValuePair[] };
export type KeyValuePair = { export type KeyValuePair = {
name: string; name: string;
value: string; value: string;
@ -199,6 +241,10 @@ export const defaultActionRequestBody = `{
} }
}`; }`;
export const defaultActionResponseBody = `{
"response": {{$body}},
}`;
export const defaultEventRequestBody = `{ export const defaultEventRequestBody = `{
"table": { "table": {
"name": {{$body.table.name}}, "name": {{$body.table.name}},

View File

@ -12,10 +12,14 @@ import {
RequestTransformState, RequestTransformState,
RequestTransformStateBody, RequestTransformStateBody,
ResponseTransformState, ResponseTransformState,
ResponseTransformStateBody,
} from './stateDefaults'; } from './stateDefaults';
import { isEmpty, isJsonString } from '../utils/jsUtils'; import { isEmpty, isJsonString } from '../utils/jsUtils';
import { Nullable } from '../utils/tsUtils'; import { Nullable } from '../utils/tsUtils';
import { requestBodyActionState } from './requestTransformState'; import {
requestBodyActionState,
responseBodyActionState,
} from './requestTransformState';
export const getPairsObjFromArray = ( export const getPairsObjFromArray = (
pairs: KeyValuePair[] pairs: KeyValuePair[]
@ -177,12 +181,21 @@ export const getRequestTransformObject = (
}; };
export const getResponseTransformObject = ( export const getResponseTransformObject = (
transformState: ResponseTransformState responseTransformState: ResponseTransformState
): ResponseTranform => ({ ) => {
const isResponsePayloadTransform =
responseTransformState.isResponsePayloadTransform;
if (!isResponsePayloadTransform) return null;
const obj: ResponseTranform = {
version: 2, version: 2,
body: getTransformBodyServer(transformState.requestBody), body: getTransformBodyServer(responseTransformState.responseBody),
template_engine: transformState.templatingEngine, template_engine: responseTransformState.templatingEngine,
}); };
return obj;
};
const getErrorFromCode = (data: Record<string, any>) => { const getErrorFromCode = (data: Record<string, any>) => {
const errorCode = data.code ? data.code : ''; const errorCode = data.code ? data.code : '';
@ -439,6 +452,15 @@ const getRequestTransformBody = (
}; };
}; };
const getResponseTransformBody = (
responseTransform: ResponseTranform
): ResponseTransformStateBody => {
return {
action: responseBodyActionState.transformApplicationJson,
template: responseTransform.body?.template ?? '',
};
};
export const getTransformState = ( export const getTransformState = (
transform: RequestTransform, transform: RequestTransform,
sampleInput: string sampleInput: string
@ -469,6 +491,17 @@ export const getTransformState = (
templatingEngine: transform?.template_engine ?? 'Kriti', templatingEngine: transform?.template_engine ?? 'Kriti',
}); });
export const getResponseTransformState = (
responseTransform: ResponseTranform
): ResponseTransformState => ({
version: responseTransform?.version,
templatingEngine: responseTransform?.template_engine ?? 'Kriti',
isResponsePayloadTransform: !!responseTransform?.body,
responseBody: getResponseTransformBody(responseTransform),
responseSampleInput: '',
responseBodyError: '',
});
export const capitaliseFirstLetter = (val: string) => export const capitaliseFirstLetter = (val: string) =>
`${val[0].toUpperCase()}${val.slice(1)}`; `${val[0].toUpperCase()}${val.slice(1)}`;

View File

@ -29,6 +29,10 @@ import {
setRequestContentType, setRequestContentType,
setRequestUrlTransform, setRequestUrlTransform,
setRequestPayloadTransform, setRequestPayloadTransform,
setResponsePayloadTransform,
setResponseBody,
responseTransformReducer,
getActionResponseTransformDefaultState,
} from '@/components/Common/ConfigureTransformation/requestTransformState'; } from '@/components/Common/ConfigureTransformation/requestTransformState';
import { import {
RequestTransformContentType, RequestTransformContentType,
@ -37,6 +41,7 @@ import {
import { import {
KeyValuePair, KeyValuePair,
RequestTransformStateBody, RequestTransformStateBody,
ResponseTransformStateBody,
} from '@/components/Common/ConfigureTransformation/stateDefaults'; } from '@/components/Common/ConfigureTransformation/stateDefaults';
import ConfigureTransformation from '@/components/Common/ConfigureTransformation/ConfigureTransformation'; import ConfigureTransformation from '@/components/Common/ConfigureTransformation/ConfigureTransformation';
import ActionEditor from '../Common/components/ActionEditor'; import ActionEditor from '../Common/components/ActionEditor';
@ -82,6 +87,11 @@ const AddAction: React.FC<AddActionProps> = ({
getActionRequestTransformDefaultState() getActionRequestTransformDefaultState()
); );
const [responseTransformState, responseTransformDispatch] = useReducer(
responseTransformReducer,
getActionResponseTransformDefaultState()
);
useEffect(() => { useEffect(() => {
if (readOnlyMode) if (readOnlyMode)
dispatch( dispatch(
@ -120,7 +130,7 @@ const AddAction: React.FC<AddActionProps> = ({
} = actionDefinition; } = actionDefinition;
const onSubmit = () => { const onSubmit = () => {
dispatch(createAction(transformState)); dispatch(createAction(transformState, responseTransformState));
}; };
const setHeaders = (hs: Header[]) => { const setHeaders = (hs: Header[]) => {
@ -222,6 +232,14 @@ const AddAction: React.FC<AddActionProps> = ({
transformDispatch(setRequestPayloadTransform(data)); transformDispatch(setRequestPayloadTransform(data));
}; };
const responsePayloadTransformOnChange = (data: boolean) => {
responseTransformDispatch(setResponsePayloadTransform(data));
};
const responseBodyOnChange = (responseBody: ResponseTransformStateBody) => {
responseTransformDispatch(setResponseBody(responseBody));
};
// we send separate requests for the `url` preview and `body` preview, as in case of error, // we send separate requests for the `url` preview and `body` preview, as in case of error,
// we will not be able to resolve if the error is with url or body transform, with the current state of `test_webhook_transform` api // we will not be able to resolve if the error is with url or body transform, with the current state of `test_webhook_transform` api
useEffect(() => { useEffect(() => {
@ -357,7 +375,8 @@ const AddAction: React.FC<AddActionProps> = ({
<ConfigureTransformation <ConfigureTransformation
transformationType="action" transformationType="action"
state={transformState} requestTransfromState={transformState}
responseTransformState={responseTransformState}
resetSampleInput={resetSampleInput} resetSampleInput={resetSampleInput}
envVarsOnChange={envVarsOnChange} envVarsOnChange={envVarsOnChange}
sessionVarsOnChange={sessionVarsOnChange} sessionVarsOnChange={sessionVarsOnChange}
@ -370,6 +389,8 @@ const AddAction: React.FC<AddActionProps> = ({
requestContentTypeOnChange={requestContentTypeOnChange} requestContentTypeOnChange={requestContentTypeOnChange}
requestUrlTransformOnChange={requestUrlTransformOnChange} requestUrlTransformOnChange={requestUrlTransformOnChange}
requestPayloadTransformOnChange={requestPayloadTransformOnChange} requestPayloadTransformOnChange={requestPayloadTransformOnChange}
responsePayloadTransformOnChange={responsePayloadTransformOnChange}
responseBodyOnChange={responseBodyOnChange}
/> />
<div> <div>

View File

@ -12,6 +12,7 @@ import {
parseValidateApiData, parseValidateApiData,
getValidateTransformOptions, getValidateTransformOptions,
getTransformState, getTransformState,
getResponseTransformState,
} from '@/components/Common/ConfigureTransformation/utils'; } from '@/components/Common/ConfigureTransformation/utils';
import { Button } from '@/new-components/Button'; import { Button } from '@/new-components/Button';
import requestAction from '@/utils/requestAction'; import requestAction from '@/utils/requestAction';
@ -34,10 +35,16 @@ import {
setRequestUrlTransform, setRequestUrlTransform,
setRequestPayloadTransform, setRequestPayloadTransform,
setRequestTransformState, setRequestTransformState,
responseTransformReducer,
getActionResponseTransformDefaultState,
setResponsePayloadTransform,
setResponseBody,
setResponseTransformState,
} from '@/components/Common/ConfigureTransformation/requestTransformState'; } from '@/components/Common/ConfigureTransformation/requestTransformState';
import { import {
KeyValuePair, KeyValuePair,
RequestTransformStateBody, RequestTransformStateBody,
ResponseTransformStateBody,
} from '@/components/Common/ConfigureTransformation/stateDefaults'; } from '@/components/Common/ConfigureTransformation/stateDefaults';
import { import {
RequestTransformContentType, RequestTransformContentType,
@ -106,6 +113,11 @@ const ModifyAction: React.FC<ModifyProps> = ({
getActionRequestTransformDefaultState() getActionRequestTransformDefaultState()
); );
const [responseTransformState, responseTransformDispatch] = useReducer(
responseTransformReducer,
getActionResponseTransformDefaultState()
);
// initialize action state // initialize action state
const init = () => { const init = () => {
const modifyState = getModifyState(currentAction, allTypes); const modifyState = getModifyState(currentAction, allTypes);
@ -128,6 +140,16 @@ const ModifyAction: React.FC<ModifyProps> = ({
setRequestTransformState(getActionRequestTransformDefaultState()) setRequestTransformState(getActionRequestTransformDefaultState())
); );
} }
if (currentAction?.definition?.response_transform) {
const responseState = getResponseTransformState(
currentAction?.definition?.response_transform
);
responseTransformDispatch(setResponseTransformState(responseState));
} else {
responseTransformDispatch(
setResponseTransformState(getActionResponseTransformDefaultState())
);
}
}; };
useEffect(init, [currentAction, allTypes, dispatch]); useEffect(init, [currentAction, allTypes, dispatch]);
@ -155,9 +177,8 @@ const ModifyAction: React.FC<ModifyProps> = ({
) => { ) => {
dispatch(setTypeDefinition(value, error as any, timer, ast)); dispatch(setTypeDefinition(value, error as any, timer, ast));
}; };
const onSave = () => { const onSave = () => {
dispatch(saveAction(currentAction, transformState)); dispatch(saveAction(currentAction, transformState, responseTransformState));
}; };
const onDelete = () => { const onDelete = () => {
@ -245,6 +266,14 @@ const ModifyAction: React.FC<ModifyProps> = ({
transformDispatch(setRequestPayloadTransform(data)); transformDispatch(setRequestPayloadTransform(data));
}; };
const responsePayloadTransformOnChange = (data: boolean) => {
responseTransformDispatch(setResponsePayloadTransform(data));
};
const responseBodyOnChange = (responseBody: ResponseTransformStateBody) => {
responseTransformDispatch(setResponseBody(responseBody));
};
useEffect(() => { useEffect(() => {
requestUrlErrorOnChange(''); requestUrlErrorOnChange('');
requestUrlPreviewOnChange(''); requestUrlPreviewOnChange('');
@ -405,7 +434,8 @@ const ModifyAction: React.FC<ModifyProps> = ({
<ConfigureTransformation <ConfigureTransformation
transformationType="action" transformationType="action"
state={transformState} requestTransfromState={transformState}
responseTransformState={responseTransformState}
resetSampleInput={resetSampleInput} resetSampleInput={resetSampleInput}
envVarsOnChange={envVarsOnChange} envVarsOnChange={envVarsOnChange}
sessionVarsOnChange={sessionVarsOnChange} sessionVarsOnChange={sessionVarsOnChange}
@ -418,6 +448,10 @@ const ModifyAction: React.FC<ModifyProps> = ({
requestContentTypeOnChange={requestContentTypeOnChange} requestContentTypeOnChange={requestContentTypeOnChange}
requestUrlTransformOnChange={requestUrlTransformOnChange} requestUrlTransformOnChange={requestUrlTransformOnChange}
requestPayloadTransformOnChange={requestPayloadTransformOnChange} requestPayloadTransformOnChange={requestPayloadTransformOnChange}
responsePayloadTransformOnChange={
responsePayloadTransformOnChange
}
responseBodyOnChange={responseBodyOnChange}
/> />
<div className="flex items-start mb-lg"> <div className="flex items-start mb-lg">

View File

@ -64,7 +64,8 @@ import {
getResponseTransformObject, getResponseTransformObject,
} from '../../Common/ConfigureTransformation/utils'; } from '../../Common/ConfigureTransformation/utils';
export const createAction = transformState => (dispatch, getState) => { export const createAction =
(transformState, responseTransformState) => (dispatch, getState) => {
const { add: rawState } = getState().actions; const { add: rawState } = getState().actions;
const existingTypesList = customTypesSelector(getState()); const existingTypesList = customTypesSelector(getState());
const allActions = actionsSelector(getState()); const allActions = actionsSelector(getState());
@ -108,7 +109,9 @@ export const createAction = transformState => (dispatch, getState) => {
}; };
const requestTransform = getRequestTransformObject(transformState); const requestTransform = getRequestTransformObject(transformState);
const responseTransform = getResponseTransformObject(
responseTransformState
);
const validationError = getStateValidationError(state, existingTypesList); const validationError = getStateValidationError(state, existingTypesList);
if (validationError) { if (validationError) {
return dispatch(showErrorNotification(validationError)); return dispatch(showErrorNotification(validationError));
@ -147,15 +150,9 @@ export const createAction = transformState => (dispatch, getState) => {
); );
migration.add(customFieldsQueryUp, customFieldsQueryDown); migration.add(customFieldsQueryUp, customFieldsQueryDown);
const actionQueryUp = requestTransform const actionQueryUp = generateCreateActionQuery(
? generateCreateActionQuery(
state.name, state.name,
generateActionDefinition(state, requestTransform), generateActionDefinition(state, requestTransform, responseTransform),
actionComment
)
: generateCreateActionQuery(
state.name,
generateActionDefinition(state),
actionComment actionComment
); );
@ -195,10 +192,11 @@ export const createAction = transformState => (dispatch, getState) => {
successMsg, successMsg,
errorMsg errorMsg
); );
}; };
export const saveAction = export const saveAction =
(currentAction, transformState) => (dispatch, getState) => { (currentAction, transformState, responseTransformState) =>
(dispatch, getState) => {
const { modify: rawState } = getState().actions; const { modify: rawState } = getState().actions;
const existingTypesList = customTypesSelector(getState()); const existingTypesList = customTypesSelector(getState());
const { const {
@ -241,7 +239,9 @@ export const saveAction =
}; };
const requestTransform = getRequestTransformObject(transformState); const requestTransform = getRequestTransformObject(transformState);
const responseTransform = getResponseTransformObject(transformState); const responseTransform = getResponseTransformObject(
responseTransformState
);
const validationError = getStateValidationError(state); const validationError = getStateValidationError(state);
if (validationError) { if (validationError) {
@ -269,7 +269,6 @@ export const saveAction =
); );
const dropCurrentActionQuery = generateDropActionQuery(currentAction.name); const dropCurrentActionQuery = generateDropActionQuery(currentAction.name);
const updateCurrentActionQuery = getUpdateActionQuery( const updateCurrentActionQuery = getUpdateActionQuery(
generateActionDefinition(state, requestTransform, responseTransform), generateActionDefinition(state, requestTransform, responseTransform),
currentAction.name, currentAction.name,
@ -281,15 +280,9 @@ export const saveAction =
currentAction.comment currentAction.comment
); );
const createNewActionQuery = requestTransform const createNewActionQuery = generateCreateActionQuery(
? generateCreateActionQuery(
state.name, state.name,
generateActionDefinition(state, requestTransform), generateActionDefinition(state, requestTransform, responseTransform),
actionComment
)
: generateCreateActionQuery(
state.name,
generateActionDefinition(state),
actionComment actionComment
); );

View File

@ -374,7 +374,7 @@ const Add: React.FC<Props> = props => {
/> />
<ConfigureTransformation <ConfigureTransformation
transformationType="event" transformationType="event"
state={transformState} requestTransfromState={transformState}
resetSampleInput={resetSampleInput} resetSampleInput={resetSampleInput}
envVarsOnChange={envVarsOnChange} envVarsOnChange={envVarsOnChange}
sessionVarsOnChange={sessionVarsOnChange} sessionVarsOnChange={sessionVarsOnChange}

View File

@ -388,7 +388,7 @@ const Modify: React.FC<Props> = props => {
/> />
<ConfigureTransformation <ConfigureTransformation
transformationType="event" transformationType="event"
state={transformState} requestTransfromState={transformState}
resetSampleInput={resetSampleInput} resetSampleInput={resetSampleInput}
envVarsOnChange={envVarsOnChange} envVarsOnChange={envVarsOnChange}
sessionVarsOnChange={sessionVarsOnChange} sessionVarsOnChange={sessionVarsOnChange}