console: support naming convention in source customization for postgres DB [CON-297]

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4823
GitOrigin-RevId: a6a3bfcb9c7e16dd551d14dde3d424d07b8f1d15
This commit is contained in:
Varun Choudhary 2022-06-23 12:20:15 +05:30 committed by hasura-bot
parent fbfa32207d
commit 866164357c
13 changed files with 79 additions and 5 deletions

View File

@ -4,7 +4,8 @@
### Bug fixes and improvements ### Bug fixes and improvements
console: Hide TimescaleDB internal schema from data tab - console: Hide TimescaleDB internal schema from data tab
- console: support naming convention in source customization for postgres DB [CON-297]
## v2.9.0-beta.1 ## v2.9.0-beta.1

View File

@ -423,7 +423,9 @@ const ConnectDatabaseForm: React.FC<ConnectDatabaseFormProps> = ({
<GraphQLFieldCustomizationContainer <GraphQLFieldCustomizationContainer
rootFields={connectionDBState.customization?.rootFields} rootFields={connectionDBState.customization?.rootFields}
typeNames={connectionDBState.customization?.typeNames} typeNames={connectionDBState.customization?.typeNames}
namingConvention={connectionDBState.customization?.namingConvention}
connectionDBStateDispatch={connectionDBStateDispatch} connectionDBStateDispatch={connectionDBStateDispatch}
connectionDBState={connectionDBState}
/> />
)} )}
</div> </div>

View File

@ -96,6 +96,8 @@ const ConnectDatabase: React.FC<ConnectDatabaseProps> = props => {
customization: { customization: {
rootFields: currentSourceInfo?.customization?.root_fields, rootFields: currentSourceInfo?.customization?.root_fields,
typeNames: currentSourceInfo?.customization?.type_names, typeNames: currentSourceInfo?.customization?.type_names,
namingConvention:
currentSourceInfo?.customization?.naming_convention,
}, },
}, },
}); });

View File

@ -1,5 +1,8 @@
import { getSupportedDrivers } from '@/dataSources';
import { namingConventionOptions } from '@/metadata/types';
import { Collapse } from '@/new-components/Collapse'; import { Collapse } from '@/new-components/Collapse';
import React from 'react'; import React from 'react';
import { ConnectDBState } from '../state';
type FormRowProps = { type FormRowProps = {
name: string; name: string;
@ -62,7 +65,8 @@ export type CustomizationFieldName =
| 'rootFields.prefix' | 'rootFields.prefix'
| 'rootFields.suffix' | 'rootFields.suffix'
| 'typeNames.prefix' | 'typeNames.prefix'
| 'typeNames.suffix'; | 'typeNames.suffix'
| 'namingConvention';
export type GraphQLFieldCustomizationProps = { export type GraphQLFieldCustomizationProps = {
rootFields?: { rootFields?: {
@ -74,13 +78,17 @@ export type GraphQLFieldCustomizationProps = {
prefix?: string; prefix?: string;
suffix?: string; suffix?: string;
}; };
namingConvention?: namingConventionOptions;
onChange: (fieldName: CustomizationFieldName, fieldValue: string) => void; onChange: (fieldName: CustomizationFieldName, fieldValue: string) => void;
connectionDBState?: ConnectDBState;
}; };
export const GraphQLFieldCustomization: React.FC<GraphQLFieldCustomizationProps> = ({ export const GraphQLFieldCustomization: React.FC<GraphQLFieldCustomizationProps> = ({
rootFields, rootFields,
typeNames, typeNames,
namingConvention,
onChange, onChange,
connectionDBState,
}) => { }) => {
return ( return (
<div> <div>
@ -94,6 +102,34 @@ export const GraphQLFieldCustomization: React.FC<GraphQLFieldCustomizationProps>
tooltip="Set a namespace or add a prefix / suffix to the root fields and types for the database's objects in the GraphQL API" tooltip="Set a namespace or add a prefix / suffix to the root fields and types for the database's objects in the GraphQL API"
> >
<Collapse.Content> <Collapse.Content>
{connectionDBState?.dbType &&
getSupportedDrivers(
'connectDbForm.namingConvention'
).includes(connectionDBState?.dbType) && (
<div className="grid gap-0 grid-cols-2 grid-rows">
<label className="p-sm text-gray-600 font-semibold py-xs w-1/3">
Naming Convention
</label>
<span className="px-sm py-xs">
<select
className="form-control font-normal cursor-pointer"
onChange={e => {
if (namingConvention) {
onChange('namingConvention', e.target.value);
}
}}
value={namingConvention}
>
<option value="hasura-default">
hasura-default
</option>
<option value="graphql-default">
graphql-default
</option>
</select>
</span>
</div>
)}
<div> <div>
<div className="p-sm text-gray-600 font-semibold"> <div className="p-sm text-gray-600 font-semibold">
Root Fields Root Fields

View File

@ -22,6 +22,7 @@ const CustomizationFieldNameToActionTypeMap: Record<
'rootFields.suffix': 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_SUFFIX', 'rootFields.suffix': 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_SUFFIX',
'typeNames.prefix': 'UPDATE_CUSTOMIZATION_TYPE_NAMES_PREFIX', 'typeNames.prefix': 'UPDATE_CUSTOMIZATION_TYPE_NAMES_PREFIX',
'typeNames.suffix': 'UPDATE_CUSTOMIZATION_TYPE_NAMES_SUFFIX', 'typeNames.suffix': 'UPDATE_CUSTOMIZATION_TYPE_NAMES_SUFFIX',
namingConvention: 'UPDATE_CUSTOMIZATION_NAMING_CONVENTION',
}; };
export const getActionType = ( export const getActionType = (
@ -32,7 +33,9 @@ export const getActionType = (
export const GraphQLFieldCustomizationContainer: React.FC<GraphQLFieldCustomizationContainerProps> = ({ export const GraphQLFieldCustomizationContainer: React.FC<GraphQLFieldCustomizationContainerProps> = ({
rootFields, rootFields,
typeNames, typeNames,
namingConvention,
connectionDBStateDispatch, connectionDBStateDispatch,
connectionDBState,
}) => { }) => {
const onChange = (fieldName: CustomizationFieldName, fieldValue: string) => { const onChange = (fieldName: CustomizationFieldName, fieldValue: string) => {
const actionType = getActionType(fieldName); const actionType = getActionType(fieldName);
@ -47,7 +50,9 @@ export const GraphQLFieldCustomizationContainer: React.FC<GraphQLFieldCustomizat
<GraphQLFieldCustomization <GraphQLFieldCustomization
rootFields={rootFields} rootFields={rootFields}
typeNames={typeNames} typeNames={typeNames}
namingConvention={namingConvention}
onChange={onChange} onChange={onChange}
connectionDBState={connectionDBState}
/> />
); );
}; };

View File

@ -10,6 +10,7 @@ import {
SSLConfigOptions, SSLConfigOptions,
IsolationLevelOptions, IsolationLevelOptions,
GraphQLFieldCustomization, GraphQLFieldCustomization,
namingConventionOptions,
} from '../../../../metadata/types'; } from '../../../../metadata/types';
export const connectionTypes = { export const connectionTypes = {
@ -71,6 +72,9 @@ export const defaultState: ConnectDBState = {
}, },
preparedStatements: false, preparedStatements: false,
isolationLevel: 'read-committed', isolationLevel: 'read-committed',
customization: {
namingConvention: 'hasura-default',
},
}; };
type DefaultStateProps = { type DefaultStateProps = {
@ -156,7 +160,6 @@ export const connectDataSource = (
...currentState.connectionParamState, ...currentState.connectionParamState,
}); });
} }
const data = { const data = {
driver: currentState.dbType, driver: currentState.dbType,
payload: { payload: {
@ -190,6 +193,7 @@ export const connectDataSource = (
...(checkEmpty(currentState.customization?.typeNames) && { ...(checkEmpty(currentState.customization?.typeNames) && {
typeNames: currentState.customization?.typeNames, typeNames: currentState.customization?.typeNames,
}), }),
namingConvention: currentState.customization?.namingConvention,
}, },
}), }),
}, },
@ -254,6 +258,10 @@ export type ConnectDBActions =
| { type: 'UPDATE_PREPARED_STATEMENTS'; data: boolean } | { type: 'UPDATE_PREPARED_STATEMENTS'; data: boolean }
| { type: 'UPDATE_ISOLATION_LEVEL'; data: IsolationLevelOptions } | { type: 'UPDATE_ISOLATION_LEVEL'; data: IsolationLevelOptions }
| { type: 'RESET_INPUT_STATE' } | { type: 'RESET_INPUT_STATE' }
| {
type: 'UPDATE_CUSTOMIZATION_NAMING_CONVENTION';
data: namingConventionOptions;
}
| { type: 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_NAMESPACE'; data: string } | { type: 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_NAMESPACE'; data: string }
| { type: 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_PREFIX'; data: string } | { type: 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_PREFIX'; data: string }
| { type: 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_SUFFIX'; data: string } | { type: 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_SUFFIX'; data: string }
@ -483,6 +491,14 @@ export const connectDBReducer = (
projectId: action.data, projectId: action.data,
}, },
}; };
case 'UPDATE_CUSTOMIZATION_NAMING_CONVENTION':
return {
...state,
customization: {
...state.customization,
namingConvention: action.data,
},
};
case 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_NAMESPACE': case 'UPDATE_CUSTOMIZATION_ROOT_FIELDS_NAMESPACE':
return { return {
...state, ...state,

View File

@ -216,6 +216,7 @@ export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
pool_timeout: false, pool_timeout: false,
connection_lifetime: false, connection_lifetime: false,
ssl_certificates: false, ssl_certificates: false,
namingConvention: false,
}, },
}; };

View File

@ -22,6 +22,10 @@ import {
export const supportedFeatures: DeepRequired<SupportedFeaturesType> = { export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
...PgSupportedFeatures, ...PgSupportedFeatures,
connectDbForm: {
...PgSupportedFeatures?.connectDbForm,
namingConvention: false,
},
driver: { driver: {
name: 'citus', name: 'citus',
fetchVersion: { fetchVersion: {

View File

@ -236,6 +236,7 @@ export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
pool_timeout: false, pool_timeout: false,
connection_lifetime: false, connection_lifetime: false,
ssl_certificates: false, ssl_certificates: false,
namingConvention: false,
}, },
}; };

View File

@ -742,6 +742,7 @@ export const supportedFeatures: DeepRequired<SupportedFeaturesType> = {
retries: true, retries: true,
pool_timeout: true, pool_timeout: true,
connection_lifetime: true, connection_lifetime: true,
namingConvention: true,
ssl_certificates: ssl_certificates:
globals.consoleType === 'cloud' || globals.consoleType === 'pro', globals.consoleType === 'cloud' || globals.consoleType === 'pro',
}, },

View File

@ -422,6 +422,7 @@ export type SupportedFeaturesType = {
pool_timeout: boolean; pool_timeout: boolean;
connection_lifetime: boolean; connection_lifetime: boolean;
ssl_certificates: boolean; ssl_certificates: boolean;
namingConvention: boolean;
}; };
}; };

View File

@ -12,7 +12,7 @@ type CustomizationPayloadSlice = {
customization: { customization: {
root_fields?: GraphQLFieldCustomization['rootFields']; root_fields?: GraphQLFieldCustomization['rootFields'];
type_names?: GraphQLFieldCustomization['typeNames']; type_names?: GraphQLFieldCustomization['typeNames'];
naming_convention: 'hasura-default'; naming_convention?: GraphQLFieldCustomization['namingConvention'];
}; };
}; };
@ -35,7 +35,7 @@ const adaptCustomizations = (
customization: { customization: {
...rootFields, ...rootFields,
...typeNames, ...typeNames,
naming_convention: 'hasura-default', naming_convention: customization?.namingConvention,
}, },
}; };
}; };

View File

@ -1010,6 +1010,8 @@ export type IsolationLevelOptions =
| 'repeatable-read' | 'repeatable-read'
| 'serializable'; | 'serializable';
export type namingConventionOptions = 'hasura-default' | 'graphql-default';
export interface SSLConfigOptions { export interface SSLConfigOptions {
sslmode?: SSLModeOptions; sslmode?: SSLModeOptions;
sslrootcert?: { sslrootcert?: {
@ -1052,6 +1054,7 @@ export type GraphQLFieldCustomization = {
prefix?: string; prefix?: string;
suffix?: string; suffix?: string;
}; };
namingConvention?: namingConventionOptions;
}; };
export interface SourceConnectionInfo { export interface SourceConnectionInfo {
@ -1090,6 +1093,7 @@ export interface HasuraMetadataV2 {
type GraphQLCustomizationMetadata = { type GraphQLCustomizationMetadata = {
root_fields: GraphQLFieldCustomization['rootFields']; root_fields: GraphQLFieldCustomization['rootFields'];
type_names: GraphQLFieldCustomization['typeNames']; type_names: GraphQLFieldCustomization['typeNames'];
naming_convention: GraphQLFieldCustomization['namingConvention'];
}; };
export interface MetadataDataSource { export interface MetadataDataSource {