mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
fix (console): wrong UI form for editing local relationships
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6645 GitOrigin-RevId: c63fa72340fe345fb1278723ad173059b7d9c540
This commit is contained in:
parent
5613edbef9
commit
309ede358e
@ -230,6 +230,7 @@ export const DatabaseRelationshipsTab = ({
|
|||||||
}}
|
}}
|
||||||
onComplete={onComplete}
|
onComplete={onComplete}
|
||||||
driver={driver}
|
driver={driver}
|
||||||
|
onClose={closeForm}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<FeatureFlagFloatingButton />
|
<FeatureFlagFloatingButton />
|
||||||
|
@ -168,7 +168,13 @@ export const DatabaseRelationshipsTable = ({
|
|||||||
className="flex px-2 py-0.5 items-center font-semibold rounded text-secondary mr-0.5 hover:bg-indigo-50 focus:bg-indigo-100"
|
className="flex px-2 py-0.5 items-center font-semibold rounded text-secondary mr-0.5 hover:bg-indigo-50 focus:bg-indigo-100"
|
||||||
>
|
>
|
||||||
<FaEdit className="fill-current mr-1" />
|
<FaEdit className="fill-current mr-1" />
|
||||||
Edit
|
{[
|
||||||
|
'toLocalTableFk',
|
||||||
|
'toSameTableFk',
|
||||||
|
'toLocalTableManual',
|
||||||
|
].includes(relationship.type)
|
||||||
|
? 'Rename'
|
||||||
|
: 'Edit'}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
} from '@/features/DataSource';
|
} from '@/features/DataSource';
|
||||||
import { RemoteDBRelationshipWidget } from '../RemoteDBRelationshipWidget';
|
import { RemoteDBRelationshipWidget } from '../RemoteDBRelationshipWidget';
|
||||||
import { LocalRelationshipWidget } from '../LocalDBRelationshipWidget';
|
import { LocalRelationshipWidget } from '../LocalDBRelationshipWidget';
|
||||||
|
import { RenameRelationship } from '../RenameRelationship/RenameRelationship';
|
||||||
|
|
||||||
type EditRelationshipFormProps = {
|
type EditRelationshipFormProps = {
|
||||||
driver: Driver;
|
driver: Driver;
|
||||||
@ -27,6 +28,7 @@ type EditRelationshipFormProps = {
|
|||||||
message?: string;
|
message?: string;
|
||||||
type: 'success' | 'error' | 'cancel';
|
type: 'success' | 'error' | 'cancel';
|
||||||
}) => void;
|
}) => void;
|
||||||
|
onClose?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EditRelationshipForm = ({
|
export const EditRelationshipForm = ({
|
||||||
@ -34,6 +36,7 @@ export const EditRelationshipForm = ({
|
|||||||
driver,
|
driver,
|
||||||
existingRelationship,
|
existingRelationship,
|
||||||
onComplete,
|
onComplete,
|
||||||
|
onClose,
|
||||||
}: EditRelationshipFormProps) => {
|
}: EditRelationshipFormProps) => {
|
||||||
const { data: relationship, isLoading } = useFindRelationship({
|
const { data: relationship, isLoading } = useFindRelationship({
|
||||||
dataSourceName: existingRelationship.mapping.from.source,
|
dataSourceName: existingRelationship.mapping.from.source,
|
||||||
@ -44,6 +47,20 @@ export const EditRelationshipForm = ({
|
|||||||
|
|
||||||
if (!relationship) return <>Relationship Not found in metadata</>;
|
if (!relationship) return <>Relationship Not found in metadata</>;
|
||||||
|
|
||||||
|
if (
|
||||||
|
existingRelationship.type === 'toLocalTableFk' ||
|
||||||
|
existingRelationship.type === 'toLocalTableManual' ||
|
||||||
|
existingRelationship.type === 'toSameTableFk'
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<RenameRelationship
|
||||||
|
relationship={existingRelationship}
|
||||||
|
onSuccess={onClose}
|
||||||
|
key={existingRelationship.name}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isRemoteDBRelationship(relationship)) {
|
if (isRemoteDBRelationship(relationship)) {
|
||||||
return (
|
return (
|
||||||
<RemoteDBRelationshipWidget
|
<RemoteDBRelationshipWidget
|
||||||
@ -103,6 +120,7 @@ export const EditRelationshipForm = ({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LocalRelationshipWidget
|
<LocalRelationshipWidget
|
||||||
key={relationship.name}
|
key={relationship.name}
|
||||||
|
@ -20,6 +20,7 @@ interface Props {
|
|||||||
message?: string;
|
message?: string;
|
||||||
type: 'success' | 'error' | 'cancel';
|
type: 'success' | 'error' | 'cancel';
|
||||||
}) => void;
|
}) => void;
|
||||||
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Form = ({
|
export const Form = ({
|
||||||
@ -27,6 +28,7 @@ export const Form = ({
|
|||||||
sourceTableInfo,
|
sourceTableInfo,
|
||||||
onComplete,
|
onComplete,
|
||||||
driver,
|
driver,
|
||||||
|
onClose,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
if (existingRelationship) {
|
if (existingRelationship) {
|
||||||
return (
|
return (
|
||||||
@ -36,6 +38,7 @@ export const Form = ({
|
|||||||
sourceTableInfo={sourceTableInfo}
|
sourceTableInfo={sourceTableInfo}
|
||||||
existingRelationship={existingRelationship}
|
existingRelationship={existingRelationship}
|
||||||
onComplete={onComplete}
|
onComplete={onComplete}
|
||||||
|
onClose={onClose}
|
||||||
/>
|
/>
|
||||||
</FormLayout>
|
</FormLayout>
|
||||||
);
|
);
|
||||||
|
@ -101,30 +101,34 @@ export const ManualLocalRelationshipWidget = (
|
|||||||
<div className="mb-sm">
|
<div className="mb-sm">
|
||||||
<Name />
|
<Name />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-sm">
|
|
||||||
<RelationshipType disabled={mode === 'edit'} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-12">
|
{mode === 'create' && (
|
||||||
<div className="col-span-5">
|
<div>
|
||||||
<div className="rounded bg-gray-50 border border-gray-300 p-md gap-y-4 border-l-4 border-l-green-600">
|
<div className="mb-sm w-1/2">
|
||||||
<SourceTable />
|
<RelationshipType disabled={false} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<LinkBlockHorizontal />
|
<div className="grid grid-cols-12">
|
||||||
<div className="col-span-5">
|
<div className="col-span-5">
|
||||||
<div className="rounded bg-gray-50 border border-gray-300 p-md gap-y-4 border-l-4 border-l-indigo-600">
|
<div className="rounded bg-gray-50 border border-gray-300 p-md gap-y-4 border-l-4 border-l-green-600">
|
||||||
<TargetTable disabled={mode === 'edit'} />
|
<SourceTable />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<LinkBlockHorizontal />
|
||||||
|
<div className="col-span-5">
|
||||||
|
<div className="rounded bg-gray-50 border border-gray-300 p-md gap-y-4 border-l-4 border-l-indigo-600">
|
||||||
|
<TargetTable disabled={false} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<LinkBlockVertical title="Columns Mapped To" />
|
||||||
|
|
||||||
|
<MapColumns disabled={false} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
|
||||||
<LinkBlockVertical title="Columns Mapped To" />
|
|
||||||
|
|
||||||
<MapColumns disabled={mode === 'edit'} />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
mode="primary"
|
mode="primary"
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
import { Button } from '@/new-components/Button';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { InputField, UpdatedForm } from '@/new-components/Form';
|
||||||
|
import React from 'react';
|
||||||
|
import { Relationship } from '../DatabaseRelationshipsTable/types';
|
||||||
|
import { useRenameRelationship } from './useRenameRelationship';
|
||||||
|
|
||||||
|
export const RenameRelationship = ({
|
||||||
|
relationship,
|
||||||
|
onError,
|
||||||
|
onSuccess,
|
||||||
|
}: {
|
||||||
|
relationship: Relationship;
|
||||||
|
onSuccess?: () => void;
|
||||||
|
onError?: (err: unknown) => void;
|
||||||
|
}) => {
|
||||||
|
const { renameRelationship, isLoading } = useRenameRelationship();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<UpdatedForm
|
||||||
|
schema={z.object({
|
||||||
|
name: z.string(),
|
||||||
|
})}
|
||||||
|
onSubmit={data => {
|
||||||
|
renameRelationship({
|
||||||
|
values: {
|
||||||
|
newName: data.name,
|
||||||
|
relationshipName: relationship.name,
|
||||||
|
fromTable: relationship.mapping.from.table,
|
||||||
|
fromSource: relationship.mapping.from.source,
|
||||||
|
},
|
||||||
|
onSuccess,
|
||||||
|
onError,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
options={{
|
||||||
|
defaultValues: {
|
||||||
|
name: relationship.name,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{() => (
|
||||||
|
<div>
|
||||||
|
<InputField name="name" type="text" label="Relationship Name" />
|
||||||
|
<Button type="submit" mode="primary" isLoading={isLoading}>
|
||||||
|
Rename
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</UpdatedForm>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,98 @@
|
|||||||
|
import { exportMetadata } from '@/features/DataSource';
|
||||||
|
import { Table, useMetadataMigration } from '@/features/MetadataAPI';
|
||||||
|
import { useHttpClient } from '@/features/Network';
|
||||||
|
import { useFireNotification } from '@/new-components/Notifications';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useQueryClient } from 'react-query';
|
||||||
|
|
||||||
|
type EditManualLocalRelationshipPayload = {
|
||||||
|
newName: string;
|
||||||
|
relationshipName: string;
|
||||||
|
fromTable: Table;
|
||||||
|
fromSource: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRenameRelationship = () => {
|
||||||
|
const httpClient = useHttpClient();
|
||||||
|
const { fireNotification } = useFireNotification();
|
||||||
|
const { mutate, ...rest } = useMetadataMigration();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const renameRelationship = useCallback(
|
||||||
|
async ({
|
||||||
|
values,
|
||||||
|
onSuccess,
|
||||||
|
onError,
|
||||||
|
}: {
|
||||||
|
values: EditManualLocalRelationshipPayload;
|
||||||
|
onSuccess?: () => void;
|
||||||
|
onError?: (err: unknown) => void;
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
const { resource_version, metadata } = await exportMetadata({
|
||||||
|
httpClient,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!metadata) throw Error('Unable to fetch metadata');
|
||||||
|
|
||||||
|
const metadataSource = metadata.sources.find(
|
||||||
|
s => s.name === values.fromSource
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!metadataSource) throw Error('Unable to fetch metadata source');
|
||||||
|
|
||||||
|
const driver = metadataSource.kind;
|
||||||
|
|
||||||
|
const type = 'rename_relationship';
|
||||||
|
|
||||||
|
mutate(
|
||||||
|
{
|
||||||
|
query: {
|
||||||
|
resource_version,
|
||||||
|
type: `${driver}_${type}`,
|
||||||
|
args: {
|
||||||
|
table: values.fromTable,
|
||||||
|
source: values.fromSource,
|
||||||
|
name: values.relationshipName,
|
||||||
|
new_name: values.newName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.refetchQueries([
|
||||||
|
values.fromSource,
|
||||||
|
'list_all_relationships',
|
||||||
|
]);
|
||||||
|
|
||||||
|
onSuccess?.();
|
||||||
|
|
||||||
|
fireNotification({
|
||||||
|
type: 'success',
|
||||||
|
title: 'Success!',
|
||||||
|
message: 'A relationship renamed succesfully!',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onError: err => {
|
||||||
|
onError?.(err);
|
||||||
|
fireNotification({
|
||||||
|
type: 'error',
|
||||||
|
title: 'Failed to rename relationship',
|
||||||
|
message: err?.message,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
fireNotification({
|
||||||
|
title: 'Error',
|
||||||
|
type: 'error',
|
||||||
|
message: JSON.stringify(err),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[fireNotification, httpClient, mutate, queryClient]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { renameRelationship, ...rest };
|
||||||
|
};
|
@ -37,5 +37,6 @@ export const useListAvailableAgentsFromMetadata = () => {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user