mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-20 15:09:02 +03:00
Integrate the RS-to-RS form into Remote Schema Relationship tab [CON-98]
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4107 Co-authored-by: Matt Hardman <28978422+mattshardman@users.noreply.github.com> Co-authored-by: Abhijeet Khangarot <26903230+abhi40308@users.noreply.github.com> Co-authored-by: Vijay Prasanna <11921040+vijayprasanna13@users.noreply.github.com> Co-authored-by: Varun Choudhary <68095256+Varun-Choudhary@users.noreply.github.com> GitOrigin-RevId: 32a21e0733fbaeb82a0870bdabbe0122f9382d96
This commit is contained in:
parent
6720aef26f
commit
419b19c9e7
@ -11,6 +11,7 @@
|
||||
- console: add support for setting aggregation query permissions for ms sql server
|
||||
- console: add RS-to-DB (only postgres & citus) relationships feature to remote schemas tab
|
||||
- console: remove need for clicking the Modify btn before editing a remote schema (#1193, #8262)
|
||||
- console: integrate the RS-to-RS form into Remote Schema Relationship tab
|
||||
- cli: fix remote schema metadata formatting issues (#7608)
|
||||
- cli: fix query collections metadata formatting issues (#7616)
|
||||
- docs: support for `graphql-ws` is considered GA
|
||||
|
@ -57,6 +57,7 @@ describe('check if remote schema to db relationships are created properly', () =
|
||||
'http://localhost:3000/remote-schemas/manage/source_rs/relationships'
|
||||
);
|
||||
cy.get(getElementFromAlias('add-a-new-rs-relationship')).click();
|
||||
cy.get(getElementFromAlias('radio-select-remoteDB')).click();
|
||||
cy.get(getElementFromAlias('rs-to-db-rel-name')).type('RelationshipName');
|
||||
cy.get(getElementFromAlias('select-rel-type')).select('array');
|
||||
cy.get(getElementFromAlias('select-source-type')).select('Pokemon');
|
||||
|
@ -0,0 +1,111 @@
|
||||
import { getElementFromAlias } from '../../../helpers/eventHelpers';
|
||||
import { replaceMetadata, resetMetadata } from '../../../helpers/metadata';
|
||||
|
||||
describe('check if remote schema to db relationships are created properly', () => {
|
||||
before(() => {
|
||||
// load stuff into the metadata
|
||||
replaceMetadata({
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
use_prepared_statements: true,
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
retries: 1,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
remote_schemas: [
|
||||
{
|
||||
name: 'source_rs',
|
||||
definition: {
|
||||
url: 'https://graphql-pokemon2.vercel.app/',
|
||||
timeout_seconds: 60,
|
||||
},
|
||||
comment: '',
|
||||
},
|
||||
{
|
||||
name: 'ref_rs',
|
||||
definition: {
|
||||
url: 'https://hasura-console-test.herokuapp.com/v1/graphql/',
|
||||
timeout_seconds: 60,
|
||||
},
|
||||
comment: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a new rs-to-rs relationship from source field', () => {
|
||||
cy.visit(
|
||||
'http://localhost:3000/remote-schemas/manage/source_rs/relationships'
|
||||
);
|
||||
cy.get(getElementFromAlias('add-a-new-rs-relationship')).click();
|
||||
cy.get(getElementFromAlias('radio-select-remoteSchema')).click();
|
||||
cy.get(getElementFromAlias('rs-to-rs-rel-name')).type('RelationshipName');
|
||||
cy.get(getElementFromAlias('select-source-type')).select('Pokemon');
|
||||
cy.get(getElementFromAlias('select-ref-rs')).select('ref_rs');
|
||||
cy.get('.ant-tree-switcher').first().click();
|
||||
cy.get('.ant-tree-switcher').eq(1).click();
|
||||
cy.get('.ant-tree-checkbox').eq(1).click();
|
||||
cy.get(getElementFromAlias('select-argument')).select('Source Field');
|
||||
cy.get(getElementFromAlias('selet-source-field')).select('id');
|
||||
cy.get(getElementFromAlias('add-rs-relationship')).click();
|
||||
cy.get(getElementFromAlias('remote-schema-relationships-table')).should(
|
||||
'exist'
|
||||
);
|
||||
cy.get(getElementFromAlias('remote-schema-relationships-table'))
|
||||
.find('tr')
|
||||
.should('have.length', 2);
|
||||
cy.get(getElementFromAlias('remote-schema-relationships-table')).contains(
|
||||
'td',
|
||||
'RelationshipName'
|
||||
);
|
||||
});
|
||||
it('should create a new reverse rs-to-rs relationship with static fill value', () => {
|
||||
cy.visit(
|
||||
'http://localhost:3000/remote-schemas/manage/ref_rs/relationships'
|
||||
);
|
||||
cy.get(getElementFromAlias('add-a-new-rs-relationship')).click();
|
||||
cy.get(getElementFromAlias('radio-select-remoteSchema')).click();
|
||||
cy.get(getElementFromAlias('rs-to-rs-rel-name')).type(
|
||||
'StaticRelationshipName'
|
||||
);
|
||||
cy.get(getElementFromAlias('select-source-type')).select('test');
|
||||
cy.get(getElementFromAlias('select-ref-rs')).select('source_rs');
|
||||
cy.get('.ant-tree-switcher').first().click(); // expand Query
|
||||
cy.get('.ant-tree-switcher').eq(3).click(); // expand pokemon
|
||||
cy.get('.ant-tree-checkbox').eq(1).click(); // check name argument
|
||||
cy.get(getElementFromAlias('select-argument')).select('Static Value');
|
||||
cy.get(getElementFromAlias('select-static-value')).type('Bulbasaur');
|
||||
cy.get(getElementFromAlias('add-rs-relationship')).click();
|
||||
cy.get(getElementFromAlias('remote-schema-relationships-table')).should(
|
||||
'exist'
|
||||
);
|
||||
cy.get(getElementFromAlias('remote-schema-relationships-table'))
|
||||
.find('tr')
|
||||
.should('have.length', 2);
|
||||
cy.get(getElementFromAlias('remote-schema-relationships-table')).contains(
|
||||
'td',
|
||||
'StaticRelationshipName'
|
||||
);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
// reset the metadata
|
||||
resetMetadata();
|
||||
});
|
||||
});
|
@ -3,8 +3,12 @@ import { useGetAllRemoteSchemaRelationships } from '@/features/MetadataAPI';
|
||||
import { RemoteSchemaRelationshipTable } from '@/features/RelationshipsTable';
|
||||
import { Button } from '@/new-components/Button';
|
||||
import { RiAddCircleFill } from 'react-icons/ri';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { RemoteSchemaToDbForm } from '@/features/RemoteRelationships/RemoteSchemaRelationships/components/RemoteSchemaToDB';
|
||||
import {
|
||||
RemoteSchemaToRemoteSchemaForm,
|
||||
RemoteRelOption,
|
||||
RemoteSchemaToDbForm,
|
||||
} from '@/features/RemoteRelationships';
|
||||
import { IndicatorCard } from '@/new-components/IndicatorCard';
|
||||
|
||||
type RemoteSchemaRelationRendererProp = {
|
||||
remoteSchemaName: string;
|
||||
@ -18,27 +22,46 @@ export const RemoteSchemaRelationRenderer = ({
|
||||
isError,
|
||||
} = useGetAllRemoteSchemaRelationships();
|
||||
const [isFormOpen, setIsFormOpen] = useState(false);
|
||||
const [formState, setFormState] = useState<RemoteRelOption>('remoteSchema');
|
||||
|
||||
if (isError) {
|
||||
return <div>Error in fetching remote schema relationships.</div>;
|
||||
}
|
||||
if (isLoading) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isError ? (
|
||||
<div>Error in fetching remote schema relationships.</div>
|
||||
) : isLoading ? (
|
||||
<div>Fetching remote schema relationships...</div>
|
||||
) : (
|
||||
{remoteSchemaRels?.length ? (
|
||||
<RemoteSchemaRelationshipTable
|
||||
remoteSchemaRels={remoteSchemaRels ?? []}
|
||||
remoteSchemaRels={remoteSchemaRels}
|
||||
showActionCell={false}
|
||||
remoteSchema={remoteSchemaName}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<IndicatorCard status="info">
|
||||
No remote schema relationships found!
|
||||
</IndicatorCard>
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
|
||||
{isFormOpen ? (
|
||||
<RemoteSchemaToDbForm
|
||||
sourceRemoteSchema={remoteSchemaName}
|
||||
closeHandler={() => setIsFormOpen(!isFormOpen)}
|
||||
onSuccess={() => setIsFormOpen(false)}
|
||||
/>
|
||||
formState === 'remoteSchema' ? (
|
||||
<RemoteSchemaToRemoteSchemaForm
|
||||
sourceRemoteSchema={remoteSchemaName}
|
||||
closeHandler={() => setIsFormOpen(!isFormOpen)}
|
||||
relModeHandler={setFormState}
|
||||
/>
|
||||
) : (
|
||||
<RemoteSchemaToDbForm
|
||||
sourceRemoteSchema={remoteSchemaName}
|
||||
closeHandler={() => setIsFormOpen(!isFormOpen)}
|
||||
onSuccess={() => setIsFormOpen(false)}
|
||||
relModeHandler={setFormState}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<Button
|
||||
icon={<RiAddCircleFill />}
|
||||
|
@ -0,0 +1,112 @@
|
||||
import { generateLhsFields, getFieldTypesFromType } from '../utils';
|
||||
|
||||
describe('generateLhsFields', () => {
|
||||
it('with 1 source field in the resultset', () => {
|
||||
const lhsFields = generateLhsFields({
|
||||
arguments: {
|
||||
code: '$weight',
|
||||
},
|
||||
});
|
||||
expect(lhsFields).toEqual(['weight']);
|
||||
});
|
||||
it('with multiple source field in the resultset', () => {
|
||||
const lhsFields = generateLhsFields({
|
||||
arguments: {
|
||||
filter: {
|
||||
code: {
|
||||
eq: '$minimum',
|
||||
ne: '$minimum',
|
||||
nin: '$maximum',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(lhsFields).toEqual(['minimum', 'maximum']);
|
||||
});
|
||||
it('with no source field in the resultset', () => {
|
||||
const lhsFields = generateLhsFields({
|
||||
arguments: {
|
||||
code: 'test',
|
||||
},
|
||||
});
|
||||
expect(lhsFields).toEqual([]);
|
||||
});
|
||||
it('with empty resultset', () => {
|
||||
const lhsFields = generateLhsFields({});
|
||||
expect(lhsFields).toEqual([]);
|
||||
});
|
||||
});
|
||||
describe('getFieldTypesFromType', () => {
|
||||
const remoteSchemaTypes = [
|
||||
{
|
||||
typeName: 'Query',
|
||||
fields: ['query', 'pokemons', 'pokemon'],
|
||||
},
|
||||
{
|
||||
typeName: 'Pokemon',
|
||||
fields: [
|
||||
'id',
|
||||
'number',
|
||||
'name',
|
||||
'weight',
|
||||
'height',
|
||||
'classification',
|
||||
'types',
|
||||
'resistant',
|
||||
'attacks',
|
||||
'weaknesses',
|
||||
'fleeRate',
|
||||
'maxCP',
|
||||
'evolutions',
|
||||
'evolutionRequirements',
|
||||
'maxHP',
|
||||
'image',
|
||||
],
|
||||
},
|
||||
{
|
||||
typeName: 'PokemonDimension',
|
||||
fields: ['minimum', 'maximum'],
|
||||
},
|
||||
{
|
||||
typeName: 'PokemonAttack',
|
||||
fields: ['fast', 'special'],
|
||||
},
|
||||
{
|
||||
typeName: 'Attack',
|
||||
fields: ['name', 'type', 'damage'],
|
||||
},
|
||||
{
|
||||
typeName: 'PokemonEvolutionRequirement',
|
||||
fields: ['amount', 'name'],
|
||||
},
|
||||
];
|
||||
it('with valid schemaTypes and sourceType', () => {
|
||||
const lhsFields = getFieldTypesFromType(remoteSchemaTypes, 'PokemonAttack');
|
||||
expect(lhsFields).toEqual(['fast', 'special']);
|
||||
});
|
||||
it('with valid schemaTypes and sourceType 2', () => {
|
||||
const lhsFields = getFieldTypesFromType(remoteSchemaTypes, 'Pokemon');
|
||||
expect(lhsFields).toEqual([
|
||||
'id',
|
||||
'number',
|
||||
'name',
|
||||
'weight',
|
||||
'height',
|
||||
'classification',
|
||||
'types',
|
||||
'resistant',
|
||||
'attacks',
|
||||
'weaknesses',
|
||||
'fleeRate',
|
||||
'maxCP',
|
||||
'evolutions',
|
||||
'evolutionRequirements',
|
||||
'maxHP',
|
||||
'image',
|
||||
]);
|
||||
});
|
||||
it('with invalid schemaTypes and sourceType', () => {
|
||||
const lhsFields = getFieldTypesFromType(remoteSchemaTypes, 'Pokemonss');
|
||||
expect(lhsFields).toEqual([]);
|
||||
});
|
||||
});
|
@ -23,6 +23,7 @@ export const RefRsSelector = ({ allRemoteSchemas }: RefRsSelectorProps) => {
|
||||
placeholder="Select a remote schema"
|
||||
options={rsOptions}
|
||||
labelIcon={<FaPlug />}
|
||||
dataTest="select-ref-rs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,15 +1,18 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { useRemoteSchema } from '@/features/MetadataAPI';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useTableColumns } from '@/features/SqlQueries/hooks/useTableColumns';
|
||||
import { InputField, Select } from '@/new-components/Form';
|
||||
import { MapSelector } from '@/new-components/MapSelector';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { FaLink } from 'react-icons/fa';
|
||||
import {
|
||||
LinkBlockHorizontal,
|
||||
LinkBlockVertical,
|
||||
} from '@/new-components/LinkBlock';
|
||||
import { RemoteDatabaseWidget } from '../RemoteDatabaseWidget';
|
||||
import { RsSourceTypeSelector } from '../RsSourceTypeSelector';
|
||||
import { Schema } from './schema';
|
||||
import { getTypesFromIntrospection } from './utils';
|
||||
import { getTypesFromIntrospection } from '../../utils';
|
||||
|
||||
export const FormElements = ({
|
||||
sourceRemoteSchema,
|
||||
@ -65,27 +68,7 @@ export const FormElements = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<hr className="mb-md border-gray-300" />
|
||||
|
||||
{/* relationship meta */}
|
||||
<div className="mb-md">
|
||||
<div className="grid gap-sm grid-cols-1 sm:grid-cols-2">
|
||||
<div className="grid gap-sm grid-cols-1 sm:grid-cols-2">
|
||||
<div className="bg-white shadow-sm rounded p-md border border-gray-300">
|
||||
<p className="flex items-center font-semibold text-muted">
|
||||
<label className="cursor-pointer ml-sm font-semibold">
|
||||
Remote Schema Relationship
|
||||
</label>
|
||||
</p>
|
||||
<p className="text-muted pl-6">
|
||||
Relationship from this remote schema to another
|
||||
database schema.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full sm:w-6/12 mb-md">
|
||||
<div className="w-full sm:w-6/12 my-md">
|
||||
<div className="mb-md">
|
||||
<InputField
|
||||
name="relationshipName"
|
||||
@ -123,20 +106,7 @@ export const FormElements = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* horizontal connector line */}
|
||||
<div className="col-span-2 flex relative items-center justify-center w-full py-md">
|
||||
<div
|
||||
className="flex z-10 items-center justify-center border border-gray-300 bg-white"
|
||||
style={{
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
borderRadius: '100px',
|
||||
}}
|
||||
>
|
||||
<FaLink />
|
||||
</div>
|
||||
<div className="absolute w-full border-b border-gray-300" />
|
||||
</div>
|
||||
<LinkBlockHorizontal />
|
||||
|
||||
<div className="col-span-5">
|
||||
<RemoteDatabaseWidget />
|
||||
@ -144,16 +114,7 @@ export const FormElements = ({
|
||||
</div>
|
||||
|
||||
{/* vertical connector line */}
|
||||
<div className="flex items-center w-full px-8">
|
||||
<div className="relative flex items-center justify-center h-20">
|
||||
<div className="absolute border border-l border-gray-300 h-20" />
|
||||
<div className="absolute border border-gray-300 flex items-center justify-center rounded-full h-10 w-10 bg-white">
|
||||
<FaLink />
|
||||
</div>
|
||||
</div>
|
||||
<p className="m-0 px-8 font-semibold">Type Mapped To</p>
|
||||
</div>
|
||||
|
||||
<LinkBlockVertical title="Type Mapped To" />
|
||||
<MapSelector
|
||||
types={
|
||||
remoteSchemaTypes.find(x => x.typeName === RSTypeName)?.fields ?? []
|
||||
|
@ -9,17 +9,23 @@ import { IndicatorCard } from '@/new-components/IndicatorCard';
|
||||
import { Button } from '@/new-components/Button';
|
||||
import { FormElements } from './FormElements';
|
||||
import { schema, Schema } from './schema';
|
||||
import {
|
||||
RelationshipTypeCardRadioGroup,
|
||||
RemoteRelOption,
|
||||
} from '../RemoteSchemaToRemoteSchemaForm/RelationshipTypeCardRadioGroup';
|
||||
|
||||
export type RemoteSchemaToDbFormProps = {
|
||||
sourceRemoteSchema: string;
|
||||
closeHandler?: () => void;
|
||||
onSuccess?: () => void;
|
||||
relModeHandler: (v: RemoteRelOption) => void;
|
||||
};
|
||||
|
||||
export const RemoteSchemaToDbForm = ({
|
||||
sourceRemoteSchema,
|
||||
closeHandler,
|
||||
onSuccess,
|
||||
relModeHandler,
|
||||
}: RemoteSchemaToDbFormProps) => {
|
||||
const mutation = useMetadataMigration({
|
||||
onSuccess: () => {
|
||||
@ -47,7 +53,7 @@ export const RemoteSchemaToDbForm = ({
|
||||
schema: '',
|
||||
table: '',
|
||||
typeName: '',
|
||||
source_remote_schema: sourceRemoteSchema,
|
||||
sourceRemoteSchema,
|
||||
};
|
||||
|
||||
const submit = (values: Schema) => {
|
||||
@ -95,6 +101,14 @@ export const RemoteSchemaToDbForm = ({
|
||||
Create New Relationship
|
||||
</span>
|
||||
</div>
|
||||
<hr className="mb-md border-gray-300" />
|
||||
|
||||
{/* relationship meta */}
|
||||
<RelationshipTypeCardRadioGroup
|
||||
value="remoteDB"
|
||||
onChange={relModeHandler}
|
||||
/>
|
||||
|
||||
<FormElements sourceRemoteSchema={sourceRemoteSchema} />
|
||||
{/* submit */}
|
||||
<div>
|
||||
|
@ -13,7 +13,7 @@ export const schema = z.object({
|
||||
})
|
||||
),
|
||||
typeName: z.string().min(1, { message: 'Type is required!' }),
|
||||
source_remote_schema: z.string(),
|
||||
sourceRemoteSchema: z.string(),
|
||||
});
|
||||
|
||||
export type Schema = z.infer<typeof schema>;
|
||||
|
@ -1,15 +0,0 @@
|
||||
import { checkDefaultGQLScalarType } from '@/components/Services/RemoteSchema/Permissions/utils';
|
||||
import { GraphQLSchema } from 'graphql';
|
||||
|
||||
export const getTypesFromIntrospection = (data: GraphQLSchema) => {
|
||||
return Object.entries(data.getTypeMap())
|
||||
.map(([typeName, x]) => ({
|
||||
typeName,
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
fields: Object.keys((x as any)._fields || {}),
|
||||
}))
|
||||
.filter(
|
||||
({ typeName }) =>
|
||||
!checkDefaultGQLScalarType(typeName) && !typeName.startsWith('__')
|
||||
);
|
||||
};
|
@ -89,8 +89,8 @@ export const FormElements = ({
|
||||
isError,
|
||||
} = useLoadData(sourceRemoteSchema);
|
||||
|
||||
if (isLoading) {
|
||||
return <div>Loading...</div>;
|
||||
if (isLoading && !isError) {
|
||||
return <IndicatorCard status="info">Loading...</IndicatorCard>;
|
||||
}
|
||||
|
||||
if (isError || !remoteSchemaList || !sourceRemoteSchema) {
|
||||
@ -102,38 +102,42 @@ export const FormElements = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="grid gap-4 w-full">
|
||||
<InputField name="name" label="Name" placeholder="Relationship name" />
|
||||
<>
|
||||
<div className="w-full sm:w-6/12 my-md">
|
||||
<InputField
|
||||
name="name"
|
||||
label="Name"
|
||||
placeholder="Relationship name"
|
||||
dataTest="rs-to-rs-rel-name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-12">
|
||||
{/* select the source remote schema */}
|
||||
<div className="col-span-5">
|
||||
<RsSourceTypeSelector
|
||||
types={remoteSchemaTypes.map(t => t.typeName)}
|
||||
sourceTypeKey={rsSourceTypeKey}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-12">
|
||||
<div className="col-span-5">
|
||||
<RsSourceTypeSelector
|
||||
types={remoteSchemaTypes.map(t => t.typeName)}
|
||||
sourceTypeKey={rsSourceTypeKey}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<LinkBlockHorizontal />
|
||||
<LinkBlockHorizontal />
|
||||
|
||||
{/* select the reference remote schema */}
|
||||
<div className="col-span-5">
|
||||
<RefRsSelector allRemoteSchemas={remoteSchemaList} />
|
||||
</div>
|
||||
{/* select the reference remote schema */}
|
||||
<div className="col-span-5">
|
||||
<RefRsSelector allRemoteSchemas={remoteSchemaList} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<LinkBlockVertical title="Type Mapped To" />
|
||||
|
||||
{/* relationship details */}
|
||||
<div className="grid">
|
||||
<div className="grid w-full pb-md">
|
||||
<RemoteSchemaWidget
|
||||
schemaName={refRemoteSchemaName}
|
||||
fields={fieldsForSelectedRsType}
|
||||
rootFields={['query', 'mutation']}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -61,7 +61,6 @@ export const RemoteSchemaToRemoteSchemaForm = (
|
||||
const lhs_fields = generateLhsFields(
|
||||
values.resultSet as Record<string, unknown>
|
||||
);
|
||||
// testing payload
|
||||
const requestBody = {
|
||||
type: 'create_remote_schema_remote_relationship' as allowedMetadataTypes,
|
||||
args: {
|
||||
@ -91,15 +90,15 @@ export const RemoteSchemaToRemoteSchemaForm = (
|
||||
onSubmit={submit}
|
||||
>
|
||||
{options => (
|
||||
<div className="grid gap-4 border border-gray-300 rounded shadow-sm p-4 w-full">
|
||||
<div className="flex items-center gap-4 w-full">
|
||||
<div className="grid border border-gray-300 rounded shadow-sm p-4 w-full">
|
||||
<div className="flex items-center gap-4 w-full mb-md">
|
||||
<Button type="button" size="sm" onClick={closeHandler}>
|
||||
Cancel
|
||||
</Button>
|
||||
<p className="font-semibold m-0">Create New Relationship</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<hr className="mb-md border-gray-300" />
|
||||
|
||||
<RelationshipTypeCardRadioGroup
|
||||
value="remoteSchema"
|
||||
@ -116,6 +115,7 @@ export const RemoteSchemaToRemoteSchemaForm = (
|
||||
type="submit"
|
||||
isLoading={mutation.isLoading}
|
||||
loadingText="Creating relationship"
|
||||
data-test="add-rs-relationship"
|
||||
>
|
||||
Add Relationship
|
||||
</Button>
|
||||
|
@ -1 +1,2 @@
|
||||
export * from './RemoteSchemaToRemoteSchemaForm';
|
||||
export * from './RelationshipTypeCardRadioGroup';
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import 'antd/lib/tree/style/index.css';
|
||||
import { Tree as AntTree } from 'antd';
|
||||
import { GraphQLSchema } from 'graphql';
|
||||
import { EventDataNode } from 'antd/lib/tree';
|
||||
import './index.css';
|
||||
import {
|
||||
AllowedRootFields,
|
||||
AntdTreeNode,
|
||||
|
@ -113,6 +113,7 @@ export const ArgValueForm = ({
|
||||
className={fieldStyle}
|
||||
value={localArgValue.kind}
|
||||
onChange={changeInputType}
|
||||
data-test="select-argument"
|
||||
>
|
||||
<option disabled>Select an arugment...</option>
|
||||
{argValueTypeOptions.map(option => (
|
||||
@ -133,6 +134,7 @@ export const ArgValueForm = ({
|
||||
className={fieldStyle}
|
||||
value={localArgValue.value}
|
||||
onChange={changeInputColumnValue}
|
||||
data-test="selet-source-field"
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Field...
|
||||
@ -154,6 +156,7 @@ export const ArgValueForm = ({
|
||||
className={fieldStyle}
|
||||
value={localArgValue.value}
|
||||
onChange={e => onValueChangeHandler(e.target.value)}
|
||||
data-test="select-static-value"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
@ -0,0 +1,547 @@
|
||||
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
|
||||
/* stylelint-disable no-duplicate-selectors */
|
||||
/* stylelint-disable */
|
||||
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
|
||||
@-webkit-keyframes antCheckboxEffect {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.6);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes antCheckboxEffect {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.6);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ant-tree-node-fx-do-not-use {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes ant-tree-node-fx-do-not-use {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode {
|
||||
position: relative;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 4px;
|
||||
left: 0;
|
||||
transition: background-color 0.3s;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode:hover::before {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode > * {
|
||||
z-index: 1;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-switcher {
|
||||
transition: color 0.3s;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-node-content-wrapper {
|
||||
border-radius: 0;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-node-content-wrapper:hover {
|
||||
background: transparent;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode .ant-tree-node-content-wrapper.ant-tree-node-selected {
|
||||
color: #fff;
|
||||
background: transparent;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode-selected:hover::before,
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode-selected::before {
|
||||
background: #1890ff;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-switcher {
|
||||
color: #fff;
|
||||
}
|
||||
.ant-tree.ant-tree-directory .ant-tree-treenode-selected .ant-tree-node-content-wrapper {
|
||||
color: #fff;
|
||||
background: transparent;
|
||||
}
|
||||
.ant-tree-checkbox {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5715;
|
||||
list-style: none;
|
||||
font-feature-settings: 'tnum';
|
||||
position: relative;
|
||||
top: 0.2em;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-inner,
|
||||
.ant-tree-checkbox:hover .ant-tree-checkbox-inner,
|
||||
.ant-tree-checkbox-input:focus + .ant-tree-checkbox-inner {
|
||||
border-color: #1890ff;
|
||||
}
|
||||
.ant-tree-checkbox-checked::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid #1890ff;
|
||||
border-radius: 2px;
|
||||
visibility: hidden;
|
||||
-webkit-animation: antCheckboxEffect 0.36s ease-in-out;
|
||||
animation: antCheckboxEffect 0.36s ease-in-out;
|
||||
-webkit-animation-fill-mode: backwards;
|
||||
animation-fill-mode: backwards;
|
||||
content: '';
|
||||
}
|
||||
.ant-tree-checkbox:hover::after,
|
||||
.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox::after {
|
||||
visibility: visible;
|
||||
}
|
||||
.ant-tree-checkbox-inner {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
direction: ltr;
|
||||
background-color: #fff;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
border-collapse: separate;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.ant-tree-checkbox-inner::after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 21.5%;
|
||||
display: table;
|
||||
width: 5.71428571px;
|
||||
height: 9.14285714px;
|
||||
border: 2px solid #fff;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
transform: rotate(45deg) scale(0) translate(-50%, -50%);
|
||||
opacity: 0;
|
||||
transition: all 0.1s cubic-bezier(0.71, -0.46, 0.88, 0.6), opacity 0.1s;
|
||||
content: ' ';
|
||||
}
|
||||
.ant-tree-checkbox-input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
}
|
||||
.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after {
|
||||
position: absolute;
|
||||
display: table;
|
||||
border: 2px solid #fff;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
transform: rotate(45deg) scale(1) translate(-50%, -50%);
|
||||
opacity: 1;
|
||||
transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
|
||||
content: ' ';
|
||||
}
|
||||
.ant-tree-checkbox-checked .ant-tree-checkbox-inner {
|
||||
background-color: #1890ff;
|
||||
border-color: #1890ff;
|
||||
}
|
||||
.ant-tree-checkbox-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.ant-tree-checkbox-disabled.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after {
|
||||
border-color: rgba(0, 0, 0, 0.25);
|
||||
-webkit-animation-name: none;
|
||||
animation-name: none;
|
||||
}
|
||||
.ant-tree-checkbox-disabled .ant-tree-checkbox-input {
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
.ant-tree-checkbox-disabled .ant-tree-checkbox-inner {
|
||||
background-color: #f5f5f5;
|
||||
border-color: #d9d9d9 !important;
|
||||
}
|
||||
.ant-tree-checkbox-disabled .ant-tree-checkbox-inner::after {
|
||||
border-color: #f5f5f5;
|
||||
border-collapse: separate;
|
||||
-webkit-animation-name: none;
|
||||
animation-name: none;
|
||||
}
|
||||
.ant-tree-checkbox-disabled + span {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.ant-tree-checkbox-disabled:hover::after,
|
||||
.ant-tree-checkbox-wrapper:hover .ant-tree-checkbox-disabled::after {
|
||||
visibility: hidden;
|
||||
}
|
||||
.ant-tree-checkbox-wrapper {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5715;
|
||||
list-style: none;
|
||||
font-feature-settings: 'tnum';
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
line-height: unset;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ant-tree-checkbox-wrapper::after {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
content: '\a0';
|
||||
}
|
||||
.ant-tree-checkbox-wrapper.ant-tree-checkbox-wrapper-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.ant-tree-checkbox-wrapper + .ant-tree-checkbox-wrapper {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.ant-tree-checkbox + span {
|
||||
padding-right: 8px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
.ant-tree-checkbox-group {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5715;
|
||||
list-style: none;
|
||||
font-feature-settings: 'tnum';
|
||||
display: inline-block;
|
||||
}
|
||||
.ant-tree-checkbox-group-item {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.ant-tree-checkbox-group-item:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.ant-tree-checkbox-group-item + .ant-tree-checkbox-group-item {
|
||||
margin-left: 0;
|
||||
}
|
||||
.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner {
|
||||
background-color: #fff;
|
||||
border-color: #d9d9d9;
|
||||
}
|
||||
.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner::after {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: #1890ff;
|
||||
border: 0;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
opacity: 1;
|
||||
content: ' ';
|
||||
}
|
||||
.ant-tree-checkbox-indeterminate.ant-tree-checkbox-disabled .ant-tree-checkbox-inner::after {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
border-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.ant-tree {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
font-variant: tabular-nums;
|
||||
line-height: 1.5715;
|
||||
list-style: none;
|
||||
font-feature-settings: 'tnum';
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
.ant-tree-focused:not(:hover):not(.ant-tree-active-focused) {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
.ant-tree-list-holder-inner {
|
||||
align-items: flex-start;
|
||||
}
|
||||
.ant-tree.ant-tree-block-node .ant-tree-list-holder-inner {
|
||||
align-items: stretch;
|
||||
}
|
||||
.ant-tree.ant-tree-block-node .ant-tree-list-holder-inner .ant-tree-node-content-wrapper {
|
||||
flex: auto;
|
||||
}
|
||||
.ant-tree.ant-tree-block-node .ant-tree-list-holder-inner .ant-tree-treenode.dragging {
|
||||
position: relative;
|
||||
}
|
||||
.ant-tree.ant-tree-block-node .ant-tree-list-holder-inner .ant-tree-treenode.dragging::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 4px;
|
||||
left: 0;
|
||||
border: 1px solid #1890ff;
|
||||
opacity: 0;
|
||||
-webkit-animation: ant-tree-node-fx-do-not-use 0.3s;
|
||||
animation: ant-tree-node-fx-do-not-use 0.3s;
|
||||
-webkit-animation-play-state: running;
|
||||
animation-play-state: running;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
animation-fill-mode: forwards;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 0 0 4px 0;
|
||||
outline: none;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode-disabled .ant-tree-node-content-wrapper {
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode-disabled .ant-tree-node-content-wrapper:hover {
|
||||
background: transparent;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode-active .ant-tree-node-content-wrapper {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode:not(.ant-tree .ant-tree-treenode-disabled).filter-node .ant-tree-title {
|
||||
color: inherit;
|
||||
font-weight: 500;
|
||||
}
|
||||
.ant-tree-indent {
|
||||
align-self: stretch;
|
||||
white-space: nowrap;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.ant-tree-indent-unit {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
}
|
||||
.ant-tree-draggable-icon {
|
||||
width: 24px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
opacity: 0.2;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.ant-tree-treenode:hover .ant-tree-draggable-icon {
|
||||
opacity: 0.45;
|
||||
}
|
||||
.ant-tree-switcher {
|
||||
position: relative;
|
||||
flex: none;
|
||||
align-self: stretch;
|
||||
width: 24px;
|
||||
margin: 0;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.ant-tree-switcher .ant-tree-switcher-icon,
|
||||
.ant-tree-switcher .ant-select-tree-switcher-icon {
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
.ant-tree-switcher .ant-tree-switcher-icon svg,
|
||||
.ant-tree-switcher .ant-select-tree-switcher-icon svg {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
.ant-tree-switcher-noop {
|
||||
cursor: default;
|
||||
}
|
||||
.ant-tree-switcher_close .ant-tree-switcher-icon svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.ant-tree-switcher-loading-icon {
|
||||
color: #1890ff;
|
||||
}
|
||||
.ant-tree-switcher-leaf-line {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.ant-tree-switcher-leaf-line::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 12px;
|
||||
bottom: -4px;
|
||||
margin-left: -1px;
|
||||
border-right: 1px solid #d9d9d9;
|
||||
content: ' ';
|
||||
}
|
||||
.ant-tree-switcher-leaf-line::after {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
height: 14px;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
content: ' ';
|
||||
}
|
||||
.ant-tree-checkbox {
|
||||
top: initial;
|
||||
margin: 4px 8px 0 0;
|
||||
}
|
||||
.ant-tree .ant-tree-node-content-wrapper {
|
||||
position: relative;
|
||||
z-index: auto;
|
||||
min-height: 24px;
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
color: inherit;
|
||||
line-height: 24px;
|
||||
background: transparent;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s, border 0s, line-height 0s, box-shadow 0s;
|
||||
}
|
||||
.ant-tree .ant-tree-node-content-wrapper:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected {
|
||||
background-color: #bae7ff;
|
||||
}
|
||||
.ant-tree .ant-tree-node-content-wrapper .ant-tree-iconEle {
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
.ant-tree .ant-tree-node-content-wrapper .ant-tree-iconEle:empty {
|
||||
display: none;
|
||||
}
|
||||
.ant-tree-unselectable .ant-tree-node-content-wrapper:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
.ant-tree-node-content-wrapper {
|
||||
line-height: 24px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.ant-tree-node-content-wrapper .ant-tree-drop-indicator {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
height: 2px;
|
||||
background-color: #1890ff;
|
||||
border-radius: 1px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.ant-tree-node-content-wrapper .ant-tree-drop-indicator::after {
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -6px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: transparent;
|
||||
border: 2px solid #1890ff;
|
||||
border-radius: 50%;
|
||||
content: '';
|
||||
}
|
||||
.ant-tree .ant-tree-treenode.drop-container > [draggable] {
|
||||
box-shadow: 0 0 0 2px #1890ff;
|
||||
}
|
||||
.ant-tree-show-line .ant-tree-indent-unit {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
.ant-tree-show-line .ant-tree-indent-unit::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 12px;
|
||||
bottom: -4px;
|
||||
border-right: 1px solid #d9d9d9;
|
||||
content: '';
|
||||
}
|
||||
.ant-tree-show-line .ant-tree-indent-unit-end::before {
|
||||
display: none;
|
||||
}
|
||||
.ant-tree-show-line .ant-tree-switcher {
|
||||
background: #fff;
|
||||
}
|
||||
.ant-tree-show-line .ant-tree-switcher-line-icon {
|
||||
vertical-align: -0.15em;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode-leaf-last .ant-tree-switcher-leaf-line::before {
|
||||
top: auto !important;
|
||||
bottom: auto !important;
|
||||
height: 14px !important;
|
||||
}
|
||||
.ant-tree-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.ant-tree-rtl .ant-tree-node-content-wrapper[draggable='true'] .ant-tree-drop-indicator::after {
|
||||
right: -6px;
|
||||
left: unset;
|
||||
}
|
||||
.ant-tree .ant-tree-treenode-rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
.ant-tree-rtl .ant-tree-switcher_close .ant-tree-switcher-icon svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.ant-tree-rtl.ant-tree-show-line .ant-tree-indent-unit::before {
|
||||
right: auto;
|
||||
left: -13px;
|
||||
border-right: none;
|
||||
border-left: 1px solid #d9d9d9;
|
||||
}
|
||||
.ant-tree-rtl.ant-tree-checkbox {
|
||||
margin: 4px 0 0 8px;
|
||||
}
|
||||
.ant-tree-select-dropdown-rtl .ant-select-tree-checkbox {
|
||||
margin: 4px 0 0 8px;
|
||||
}
|
||||
|
3
console/src/features/RemoteRelationships/index.ts
Normal file
3
console/src/features/RemoteRelationships/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './RemoteSchemaRelationships/components/RemoteSchemaToRemoteSchemaForm/RemoteSchemaToRemoteSchemaForm';
|
||||
export * from './RemoteSchemaRelationships/components/RemoteSchemaToRemoteSchemaForm/RelationshipTypeCardRadioGroup';
|
||||
export * from './RemoteSchemaRelationships/components/RemoteSchemaToDB';
|
@ -44,10 +44,11 @@ export const CardRadioGroup = <T extends string = string>(
|
||||
className="cursor-pointer rounded-full border shadow-sm border-gray-300 hover:border-gray-400 focus:ring-yellow-400"
|
||||
onChange={() => onChange(iValue)}
|
||||
checked={value === iValue}
|
||||
data-test={`radio-select-${iValue}`}
|
||||
/>
|
||||
<label
|
||||
htmlFor={`radio-select-${iValue}`}
|
||||
className="cursor-pointer ml-sm"
|
||||
className="cursor-pointer ml-sm font-semibold"
|
||||
>
|
||||
{title}
|
||||
</label>
|
||||
|
@ -56,7 +56,7 @@ export const InputField = ({
|
||||
aria-label={wrapperProps.label}
|
||||
data-test={dataTest}
|
||||
className={clsx(
|
||||
'block w-full max-w-xl 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',
|
||||
'block w-full max-w-xl 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 placeholder-gray-500',
|
||||
maybeError
|
||||
? 'border-red-600 hover:border-red-700 placeholder-red-600 '
|
||||
: 'border-gray-300 placeholder-gray-600',
|
||||
|
Loading…
Reference in New Issue
Block a user