Skip to content

Commit db07dcf

Browse files
vijayprasanna13hasura-bot
authored andcommitted
console: new "add remote schema" page (with GQL customization)
PR-URL: hasura/graphql-engine-mono#4428 GitOrigin-RevId: d8f82ffe86fd59abb43afa195b40c2fdafabb847
1 parent f7b4d32 commit db07dcf

19 files changed

Lines changed: 4609 additions & 3543 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- console: add remote database relationships for views
1818
- console: bug fixes for RS-to-RS relationships
1919
- console: allow users to remove prefix / suffix / root field namespace from a remote schema
20+
- console: new "add remote schema" page (with GQL customization)
2021
- cli: avoid exporting hasura-specific schemas during hasura init (#8352)
2122
- cli: fix performance regression in `migrate status` command (fix #8398)
2223

console/package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

console/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"less": "3.11.1",
8989
"lodash.get": "4.4.2",
9090
"lodash.merge": "4.6.2",
91+
"lodash.pickby": "^4.6.0",
9192
"moment": "^2.26.0",
9293
"piping": "0.3.2",
9394
"prop-types": "15.7.2",
@@ -170,6 +171,7 @@
170171
"@types/jwt-decode": "2.2.1",
171172
"@types/lodash": "^4.14.159",
172173
"@types/lodash.merge": "^4.6.6",
174+
"@types/lodash.pickby": "^4.6.7",
173175
"@types/mini-css-extract-plugin": "0.9.1",
174176
"@types/optimize-css-assets-webpack-plugin": "5.0.1",
175177
"@types/react": "17.0.39",

console/src/components/Services/RemoteSchema/Add/Add.js

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,75 @@
1-
import React from 'react';
1+
import React, { useEffect } from 'react';
22
import Common from '../Common/Common';
33

44
import { addRemoteSchema, RESET } from './addRemoteSchemaReducer';
55
import Helmet from 'react-helmet';
66
import Button from '../../../Common/Button/Button';
7+
import { RemoteSchema } from '@/features/RemoteSchema';
8+
import { appPrefix, pageTitle } from '../constants';
9+
import {
10+
availableFeatureFlagIds,
11+
FeatureFlagToast,
12+
useIsFeatureFlagEnabled,
13+
} from '@/features/FeatureFlags';
14+
import { exportMetadata } from '@/metadata/actions';
15+
import _push from '../../Data/push';
716

8-
import { pageTitle } from '../constants';
17+
const Add = ({ isRequesting, dispatch, ...props }) => {
18+
const styles = require('../RemoteSchema.scss');
919

10-
class Add extends React.Component {
11-
componentWillUnmount() {
12-
this.props.dispatch({ type: RESET });
13-
}
20+
useEffect(() => {
21+
return () => {
22+
dispatch({ type: RESET });
23+
};
24+
}, []);
1425

15-
render() {
16-
const styles = require('../RemoteSchema.scss');
26+
const { isLoading, enabled } = useIsFeatureFlagEnabled(
27+
availableFeatureFlagIds.addRemoteSchemaId
28+
);
1729

18-
const { isRequesting, dispatch } = this.props;
30+
if (isLoading) {
31+
return 'Loading...';
32+
}
1933

34+
if (enabled) {
2035
return (
21-
<div className={styles.addWrapper}>
22-
<Helmet title={`Add ${pageTitle} - ${pageTitle}s | Hasura`} />
23-
<div className={styles.heading_text}>Add a new remote schema</div>
24-
<form
25-
onSubmit={e => {
26-
e.preventDefault();
27-
dispatch(addRemoteSchema());
28-
}}
29-
>
30-
<Common isNew {...this.props} />
31-
<div className={styles.commonBtn}>
32-
<Button
33-
type="submit"
34-
color="yellow"
35-
size="sm"
36-
// disabled={isRequesting} // TODO
37-
data-test="add-remote-schema-submit"
38-
>
39-
{isRequesting ? 'Adding...' : 'Add Remote Schema'}
40-
</Button>
41-
{/*
42-
<button className={styles.default_button}>Cancel</button>
43-
*/}
44-
</div>
45-
</form>
46-
</div>
36+
<RemoteSchema.Create
37+
onSuccess={remoteSchemaName => {
38+
// This only exists right now because the sidebar is reading from redux state
39+
dispatch(exportMetadata()).then(() => {
40+
dispatch(_push(`${appPrefix}/manage/${remoteSchemaName}/details`));
41+
});
42+
}}
43+
/>
4744
);
4845
}
49-
}
46+
47+
return (
48+
<div className={styles.addWrapper}>
49+
<Helmet title={`Add ${pageTitle} - ${pageTitle}s | Hasura`} />
50+
<div className={styles.heading_text}>Add a new remote schema</div>
51+
<form
52+
onSubmit={e => {
53+
e.preventDefault();
54+
dispatch(addRemoteSchema());
55+
}}
56+
>
57+
<Common isNew {...props} dispatch={dispatch} />
58+
<div className={styles.commonBtn}>
59+
<Button
60+
type="submit"
61+
color="yellow"
62+
size="sm"
63+
data-test="add-remote-schema-submit"
64+
>
65+
{isRequesting ? 'Adding...' : 'Add Remote Schema'}
66+
</Button>
67+
</div>
68+
</form>
69+
<FeatureFlagToast flagId={availableFeatureFlagIds.addRemoteSchemaId} />
70+
</div>
71+
);
72+
};
5073

5174
const mapStateToProps = state => {
5275
return {

console/src/features/FeatureFlags/availableFeatureFlags.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { FeatureFlagDefinition } from './types';
22

33
const relationshipTabTablesId = '0bea35ff-d3e9-45e9-af1b-59923bf82fa9';
4+
const addRemoteSchemaId = 'bf57c2ba-cab2-11ec-9d64-0242ac120002';
45

56
export const availableFeatureFlagIds = {
67
relationshipTabTablesId,
8+
addRemoteSchemaId,
79
};
810

911
export const availableFeatureFlags: FeatureFlagDefinition[] = [
@@ -18,4 +20,14 @@ export const availableFeatureFlags: FeatureFlagDefinition[] = [
1820
// defaultValue: false,
1921
// discussionUrl: '',
2022
// },
23+
{
24+
id: addRemoteSchemaId,
25+
title: 'New create remote schema page',
26+
description:
27+
'Try out the new Add Remote Schema page that supports GraphQL customization',
28+
section: 'remote schemas',
29+
status: 'alpha',
30+
defaultValue: false,
31+
discussionUrl: '',
32+
},
2133
];

console/src/features/MetadataAPI/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const allowedMetadataTypesArr = [
3535
'create_remote_schema_remote_relationship',
3636
'update_remote_schema_remote_relationship',
3737
'delete_remote_schema_remote_relationship',
38+
'add_remote_schema',
3839
'bulk',
3940
] as const;
4041

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import React, { useReducer } from 'react';
2+
import { ReactQueryDecorator } from '@/storybook/decorators/react-query';
3+
import { ComponentMeta, Story } from '@storybook/react';
4+
import { RemoteSchema } from '@/features/RemoteSchema';
5+
import { ReduxDecorator } from '@/storybook/decorators/redux-decorator';
6+
import { within, userEvent } from '@storybook/testing-library';
7+
import { expect } from '@storybook/jest';
8+
import { handlers } from './mocks/handlers.mock';
9+
10+
export default {
11+
title: 'RemoteSchema/components/Create',
12+
component: RemoteSchema.Create,
13+
decorators: [ReactQueryDecorator(), ReduxDecorator({})],
14+
parameters: {
15+
msw: handlers(),
16+
},
17+
} as ComponentMeta<typeof RemoteSchema.Create>;
18+
19+
export const Playground: Story = () => {
20+
const [formSuccess, toggle] = useReducer(s => !s, false);
21+
return (
22+
<>
23+
<RemoteSchema.Create onSuccess={() => toggle()} />
24+
{formSuccess ? (
25+
<p data-testid="form-result">Form saved succesfully!</p>
26+
) : null}
27+
</>
28+
);
29+
};
30+
31+
Playground.play = async ({ canvasElement }) => {
32+
const canvas = within(canvasElement);
33+
34+
userEvent.click(await canvas.findByTestId('submit'));
35+
36+
// expect error messages
37+
expect(
38+
await canvas.findByText('Remote Schema name is a required field!')
39+
).toBeInTheDocument();
40+
expect(await canvas.findByText('Invalid url')).toBeInTheDocument();
41+
42+
// Fill up the fields
43+
// const nameInput = await canvas.findByLabelText('Name');
44+
userEvent.type(await canvas.findByTestId('name'), 'test');
45+
userEvent.type(await canvas.findByTestId('url'), 'http://example.com');
46+
userEvent.type(await canvas.findByTestId('timeout_seconds'), '180');
47+
userEvent.click(await canvas.findByTestId('forward_client_headers'));
48+
49+
userEvent.click(await canvas.findByTestId('open_customization'));
50+
51+
userEvent.type(
52+
await canvas.findByTestId('customization.root_fields_namespace'),
53+
'root_field_namespace_example'
54+
);
55+
userEvent.type(
56+
await canvas.findByTestId('customization.type_prefix'),
57+
'type_prefix_example_'
58+
);
59+
userEvent.type(
60+
await canvas.findByTestId('customization.type_suffix'),
61+
'_type_suffix_example'
62+
);
63+
userEvent.type(
64+
await canvas.findByTestId('customization.query_root.parent_type'),
65+
'query_root_parent_type_example_'
66+
);
67+
userEvent.type(
68+
await canvas.findByTestId('customization.query_root.prefix'),
69+
'query_root_prefix_example_'
70+
);
71+
userEvent.type(
72+
await canvas.findByTestId('customization.query_root.suffix'),
73+
'_query_root_suffix_example'
74+
);
75+
userEvent.type(
76+
await canvas.findByTestId('customization.mutation_root.parent_type'),
77+
'mutation_root_parent_type_example_'
78+
);
79+
userEvent.type(
80+
await canvas.findByTestId('customization.mutation_root.prefix'),
81+
'mutation_root_prefix_example_'
82+
);
83+
userEvent.type(
84+
await canvas.findByTestId('customization.mutation_root.suffix'),
85+
'_mutation_root_suffix_example'
86+
);
87+
88+
userEvent.click(await canvas.findByTestId('submit'));
89+
90+
expect(
91+
await canvas.findByText('Form saved succesfully!')
92+
).toBeInTheDocument();
93+
};

0 commit comments

Comments
 (0)