console: support static scalar input types on remote schema relationships [CON-129]

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4251
Co-authored-by: Abhijeet Khangarot <26903230+abhi40308@users.noreply.github.com>
GitOrigin-RevId: 4a1278fe1b552bc01d1eda0735a9f354a2dcc83e
This commit is contained in:
Sooraj 2022-04-12 17:54:10 +05:30 committed by hasura-bot
parent d058dafae2
commit d516e67c4e
5 changed files with 141 additions and 15 deletions

View File

@ -1,4 +1,5 @@
import React from 'react';
import { GraphQLType } from 'graphql';
import { ArgValueForm } from './ArgValueForm';
import { RelationshipFields, ArgValue, HasuraRsFields } from '../../../types';
@ -12,6 +13,7 @@ type ArgFieldTitleProps = {
showForm: boolean;
argValue: ArgValue;
fields: HasuraRsFields;
argType: GraphQLType;
};
const titleStyles =
@ -25,6 +27,7 @@ export const ArgFieldTitle = ({
showForm,
argValue,
fields,
argType,
}: ArgFieldTitleProps) => {
return showForm ? (
<>
@ -35,6 +38,7 @@ export const ArgFieldTitle = ({
setRelationshipFields={setRelationshipFields}
argValue={argValue}
fields={fields}
argType={argType}
/>
</>
) : (

View File

@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react';
import { FaCircle } from 'react-icons/fa';
import { GraphQLType } from 'graphql';
import { useDebouncedEffect } from '@/hooks/useDebounceEffect';
import {
@ -9,7 +10,10 @@ import {
RelationshipFields,
} from '../../../types';
import { defaultArgValue } from '../utils';
import StaticArgValue from './StaticArgValue';
const fieldStyle =
'block w-full h-input shadow-sm rounded border border-gray-300 hover:border-gray-400 focus:outline-0 focus:ring-2 focus:ring-yellow-200 focus:border-yellow-400';
export interface ArgValueFormProps {
argKey: string;
relationshipFields: RelationshipFields[];
@ -18,11 +22,9 @@ export interface ArgValueFormProps {
>;
argValue: ArgValue;
fields: HasuraRsFields;
argType: GraphQLType;
}
const fieldStyle =
'block w-full h-input shadow-sm rounded border border-gray-300 hover:border-gray-400 focus:outline-0 focus:ring-2 focus:ring-yellow-200 focus:border-yellow-400';
const argValueTypeOptions = [
{ key: 'field', content: 'Source Field' },
{ key: 'static', content: 'Static Value' },
@ -34,6 +36,7 @@ export const ArgValueForm = ({
setRelationshipFields,
argValue,
fields,
argType,
}: ArgValueFormProps) => {
const [localArgValue, setLocalArgValue] = useState(argValue);
@ -97,7 +100,7 @@ export const ArgValueForm = ({
);
};
const onValueChangeHandler = (value: string) => {
const onValueChangeHandler = (value: string | number | boolean) => {
setLocalArgValue({ ...localArgValue, value });
};
@ -132,7 +135,7 @@ export const ArgValueForm = ({
</p>
<select
className={fieldStyle}
value={localArgValue.value}
value={localArgValue.value as string | number}
onChange={changeInputColumnValue}
data-test="selet-source-field"
>
@ -149,14 +152,11 @@ export const ArgValueForm = ({
) : (
<>
<p className="mb-xs text-muted font-semibold">Static Value</p>
<input
type="text"
name="argValue"
id="argValue"
className={fieldStyle}
value={localArgValue.value}
onChange={e => onValueChangeHandler(e.target.value)}
<StaticArgValue
data-test="select-static-value"
argType={argType}
localArgValue={localArgValue}
onValueChangeHandler={onValueChangeHandler}
/>
</>
)}

View File

@ -0,0 +1,111 @@
import { GraphQLType, isScalarType } from 'graphql';
import React, { ReactText } from 'react';
import { isJsonString } from '@/components/Common/utils/jsUtils';
import { ArgValue } from '../../../types';
const fieldStyle =
'block w-full h-input shadow-sm rounded border border-gray-300 hover:border-gray-400 focus:outline-0 focus:ring-2 focus:ring-yellow-200 focus:border-yellow-400';
type StaticArgValueProps = {
localArgValue: ArgValue;
onValueChangeHandler: (value: React.ReactText) => void;
argType: GraphQLType;
};
const SCALAR_PREFIX = '__SCALAR__';
const StaticArgValue = ({
argType,
localArgValue,
onValueChangeHandler,
}: StaticArgValueProps) => {
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (
isScalarType(argType) &&
(argType?.name === 'Int' || argType?.name === 'Float')
)
onValueChangeHandler(`${SCALAR_PREFIX}${e.target.value}`);
else onValueChangeHandler(e.target.value);
};
if (isScalarType(argType) && argType?.name === 'Int') {
let value: string | boolean | number = localArgValue.value;
if (typeof value === 'string' && value?.startsWith(SCALAR_PREFIX))
value = Number.parseInt(value?.substring(10), 10);
return (
<input
type="number"
name="argValue"
id="argValue"
className={fieldStyle}
value={value as number}
onChange={onChange}
data-test="select-static-value"
/>
);
}
if (isScalarType(argType) && argType?.name === 'Float') {
let value: string | boolean | number = localArgValue.value;
if (typeof value === 'string' && value?.startsWith(SCALAR_PREFIX))
value = Number.parseFloat(value?.substring(10));
return (
<input
type="number"
name="argValue"
id="argValue"
className={fieldStyle}
value={value as number}
onChange={onChange}
data-test="select-static-value"
/>
);
}
if (isScalarType(argType) && argType?.name === 'Boolean') {
let value: boolean | undefined;
if (
typeof localArgValue.value === 'string' &&
localArgValue.value?.startsWith(SCALAR_PREFIX)
)
value = isJsonString(localArgValue.value.substring(10))
? JSON.parse(localArgValue.value.substring(10))
: false;
return (
<div className="flex">
{[true, false].map(bool => (
<p className="flex items-center font-semibold text-muted">
<input
id={`radio-select-${bool}`}
type="radio"
x-model="relationType"
className="cursor-pointer rounded-full border shadow-sm "
onChange={() => onValueChangeHandler(`${SCALAR_PREFIX}${bool}`)}
checked={value === bool}
data-test={`radio-select-${bool}`}
/>
<label
htmlFor={`radio-select-${bool}`}
className="cursor-pointer ml-sm mr-md font-semibold"
>
{bool ? 'true' : 'false'}
</label>
</p>
))}
</div>
);
}
return (
<input
type="text"
name="argValue"
id="argValue"
className={fieldStyle}
value={localArgValue.value as ReactText}
onChange={e => onValueChangeHandler(e.target.value)}
data-test="select-static-value"
/>
);
};
export default StaticArgValue;

View File

@ -12,7 +12,12 @@ import {
isListType,
isNonNullType,
} from 'graphql';
import { isEmpty, isFloat, isNumber } from '@/components/Common/utils/jsUtils';
import {
isEmpty,
isFloat,
isJsonString,
isNumber,
} from '@/components/Common/utils/jsUtils';
import {
AllowedRootFields,
ArgValue,
@ -151,6 +156,7 @@ const buildArgElement = ({
fields={fieldOptions}
showForm={isActive && checkable}
argValue={argValue || defaultArgValue}
argType={argType}
/>
),
key: argKey,
@ -383,7 +389,12 @@ const getRemoteFieldObject = (
// if leaf, push arg value
if (ukSplit[i][depth + 1] === '__argVal') {
obj[uniqueField] = ukSplit[i][depth + 2];
const value = ukSplit[i][depth + 2];
if (value.startsWith('__SCALAR__'))
obj[uniqueField] = isJsonString(value.substring(10))
? JSON.parse(value.substring(10))
: '';
else obj[uniqueField] = value;
} else {
obj[uniqueField] = {
...getRemoteFieldObject(newUkSplit, depth + 1, maxDepth),

View File

@ -8,7 +8,7 @@ export type ArgValueKind = 'field' | 'static';
export type ArgValue = {
kind: ArgValueKind;
value: string;
value: string | number | boolean;
type: string;
};