console: integrate relationships table component to Data tab

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4353
GitOrigin-RevId: 558b4d02be04e932c02dee885d7c7d4dea983a33
This commit is contained in:
Matt Hardman 2022-06-05 13:51:00 +07:00 committed by hasura-bot
parent 384756f7be
commit 0390bd449b
10 changed files with 214 additions and 16 deletions

View File

@ -1,18 +1,30 @@
import { NormalizedTable } from '@/dataSources/types';
import React from 'react';
import { rest } from 'msw';
import { ReactQueryDecorator } from '@/storybook/decorators/react-query';
import { ComponentMeta } from '@storybook/react';
import React from 'react';
import { NormalizedTable } from '@/dataSources/types';
import { DatabaseRelationshipsTab } from './DatabaseRelationshipsTab';
import { metadata } from '../RelationshipsTable/DatabaseRelationshipsTable/mocks';
const url = 'http://localhost:8080';
export default {
title: 'Data Relationships/Database Relationships Tab',
component: DatabaseRelationshipsTab,
decorators: [ReactQueryDecorator()],
parameters: {
msw: [
rest.post(`${url}/v1/metadata`, (_req, res, ctx) =>
res(ctx.json(metadata))
),
],
},
} as ComponentMeta<typeof DatabaseRelationshipsTab>;
const tableSchema: NormalizedTable = {
table_schema: 'public',
table_name: 'author',
table_name: 'user',
table_type: 'TABLE',
is_table_tracked: true,
columns: [],
@ -21,6 +33,6 @@ const tableSchema: NormalizedTable = {
view_info: null,
};
export const Main = () => (
export const Primary = () => (
<DatabaseRelationshipsTab tableSchema={tableSchema} currentSource="default" />
);

View File

@ -1,8 +1,117 @@
import React from 'react';
import { RightContainer } from '@/components/Common/Layout/RightContainer';
import { Button } from '@/new-components/Button';
import { fireNotification } from '@/new-components/Notifications';
import { getConfirmation } from '@/components/Common/utils/jsUtils';
import { NormalizedTable } from '@/dataSources/types';
import TableHeader from '../../components/Services/Data/TableCommon/TableHeader';
import { FeatureFlagFloatingButton } from '../FeatureFlags/components/FeatureFlagFloatingButton';
import {
DatabaseRelationshipsTable,
OnClickHandlerArgs,
RowData,
} from '../RelationshipsTable/DatabaseRelationshipsTable';
import { allowedMetadataTypes, useMetadataMigration } from '../MetadataAPI';
import { DataTarget } from '../Datasources';
const createTable = (target?: DataTarget) => {
if (!target) {
return {};
}
if ('schema' in target) {
return {
name: target.table,
schema: target.schema,
};
}
if ('dataset' in target) {
return {
name: target.table,
schema: target.dataset,
};
}
return {
name: target.table,
};
};
const useFormState = () => {
const [isOpen, setIsOpen] = React.useState(false);
const [
existingRelationship,
setExistingRelationship,
] = React.useState<RowData>();
const mutation = useMetadataMigration({
onSuccess: () => {
fireNotification({
title: 'Success!',
message: 'Relationship deleted successfully',
type: 'success',
});
},
onError: () => {
fireNotification({
title: 'Error',
message: 'Error while deleting the relationship',
type: 'error',
});
},
});
const onOpen = () => {
setExistingRelationship(undefined);
setIsOpen(true);
};
const onEdit = (row?: RowData) => {
console.log(row);
setExistingRelationship(row);
setIsOpen(true);
};
const onDelete = (row?: RowData) => {
setExistingRelationship(undefined);
setIsOpen(false);
const confirmMessage = `This will permanently delete the ${row?.name} from Hasura`;
const isOk = getConfirmation(confirmMessage, true, row?.name);
if (!isOk) {
return;
}
mutation.mutate({
query: {
type: 'delete_remote_relationship' as allowedMetadataTypes,
args: {
table: createTable(row?.relationship?.target),
},
},
});
};
const onClick = ({ type, row }: OnClickHandlerArgs) => {
switch (type) {
case 'add':
onOpen();
break;
case 'edit':
onEdit(row);
break;
case 'delete':
onDelete(row);
break;
default:
setIsOpen(false);
}
};
return { isOpen, onClick, existingRelationship };
};
export const DatabaseRelationshipsTab = ({
tableSchema,
@ -11,6 +120,8 @@ export const DatabaseRelationshipsTab = ({
tableSchema: NormalizedTable;
currentSource: string;
}) => {
const { isOpen, existingRelationship, onClick } = useFormState();
return (
<RightContainer>
<TableHeader
@ -23,10 +134,29 @@ export const DatabaseRelationshipsTab = ({
count={null}
isCountEstimated
/>
<div className="p-4">
{/* remove this title when doing the actual implementation */}
<h2 className="text-md font-semibold mb-3.5">Table Relationships</h2>
<div className="py-4">
<h2 className="text-md font-semibold">Data Relationships</h2>
</div>
<DatabaseRelationshipsTable
target={{
database: currentSource,
table: tableSchema.table_name,
schema: tableSchema.table_schema,
}}
onClick={onClick}
/>
<Button mode="primary" onClick={() => onClick({ type: 'add' })}>
Add Relationship
</Button>
{/* to be replaced with actual form */}
{isOpen && (
<div className="mt-6">
Create relationship form here{' '}
{existingRelationship &&
`with existing relationship ${existingRelationship.name}`}
</div>
)}
<FeatureFlagFloatingButton />
</RightContainer>
);

View File

@ -1,14 +1,18 @@
import { RemoteRelationship } from '@/metadata/types';
export const dbToRemoteSchemaRelationships = {
target: {
database: 'default',
schema: 'public',
table: 'user',
},
remote_relationships: ([
remote_relationships: [
{
definition: {
to_source: {
relationship_type: '',
source: '',
table: { name: '', schema: '' },
field_mapping: {},
},
to_remote_schema: {
remote_field: {
test: {
@ -29,6 +33,12 @@ export const dbToRemoteSchemaRelationships = {
},
{
definition: {
to_source: {
relationship_type: '',
source: '',
table: { name: '', schema: '' },
field_mapping: {},
},
remote_field: {
test: {
arguments: {
@ -43,7 +53,7 @@ export const dbToRemoteSchemaRelationships = {
hasura_fields: ['id'],
remote_schema: 'remoteSchema3',
},
name: 'old_payload',
name: 't',
},
] as unknown) as RemoteRelationship[],
],
};

View File

@ -39,7 +39,7 @@ test('transformDbToRemoteSchema returns new and legacy formats consistently', ()
"lhs_fields": Array [
"id",
],
"relationshipName": "old_payload",
"relationshipName": "t",
"remoteSchemaName": "remoteSchema3",
"remote_field": Object {
"test": Object {

View File

@ -11,7 +11,7 @@ import {
DbToRemoteSchemaRelationship,
} from '../types';
interface TransformDbToRemoteSchemaArgs {
export interface TransformDbToRemoteSchemaArgs {
target: DataTarget;
remote_relationships: RemoteRelationship[];
}

View File

@ -2,6 +2,7 @@ import { HasuraMetadataV3 } from '@/metadata/types';
import { MetadataQueryType } from '@/metadata/queryUtils';
import { IntrospectionQuery } from 'graphql';
import { RemoteField } from '../RemoteRelationships/RemoteSchemaRelationships/types';
import { DataTarget } from '../Datasources';
export interface MetadataResponse {

View File

@ -0,0 +1,44 @@
import React from 'react';
import { FaArrowRight } from 'react-icons/fa';
import { TableRowIcon } from './TableRowIcon';
import { RowData } from '../types';
interface RelationshipCellProps {
row: RowData;
}
export const RelationshipCell = ({ row }: RelationshipCellProps) => {
// these will be updated when the table also handles other db to x relationships
const secondaryIconFromType = 'table_leaf';
const secondaryIconToType =
row.type === 'remoteSchema' ? 'remote_schema_leaf' : 'table_leaf';
return (
<div className="flex items-center gap-4">
<div className="flex gap-2 items-center">
<TableRowIcon type={row.fromType} />
{row?.source}
{row?.fieldsFrom.map(field => (
<React.Fragment key={field}>
&nbsp;/
<TableRowIcon type={secondaryIconFromType} />
{field}
</React.Fragment>
))}
</div>
<FaArrowRight className="fill-current text-sm text-muted col-span-1" />
<div className="flex gap-2 items-center">
<TableRowIcon type={row.toType} />
{row?.destination}
{row?.fieldsTo.map(field => (
<React.Fragment key={field}>
&nbsp;/
<TableRowIcon type={secondaryIconToType} />
{field}
</React.Fragment>
))}
</div>
</div>
);
};

View File

@ -7,7 +7,7 @@ import {
FaTable,
} from 'react-icons/fa';
const className = 'fill-current text-sm text-muted mr-1';
const className = 'fill-current text-sm text-muted p-0';
interface TableRowIconProps {
type:

View File

@ -1,4 +1,5 @@
export * from './ModifyActions';
export * from './RelationshipsCell';
export * from './SourceRelationshipsCell';
export * from './DestinationRelationshipCell';
export * from './TableRowIcon';

View File

@ -692,7 +692,7 @@ export interface RemoteField {
* https://hasura.io/docs/latest/graphql/core/api-reference/schema-metadata-api/remote-relationships.html#inputarguments
*/
export interface InputArguments {
[InputField: string]: PGColumn;
[InputField: string]: InputArguments | string;
}
// //////////////////////////////