support customising GraphQL fields from console (#3175)

This commit is contained in:
Rishichandra Wawhal 2019-11-06 20:00:00 +05:30 committed by Rikin Kachhia
parent 637c2cb555
commit a1a851b3d1
15 changed files with 514 additions and 38 deletions

View File

@ -238,3 +238,19 @@ export const getSchemaTables = (allTables, tableSchema) => {
export const getSchemaTableNames = (allTables, tableSchema) => {
return getSchemaTables(allTables, tableSchema).map(t => getTableName(t));
};
/*** Custom table fields utils ***/
export const getTableCustomRootFields = table => {
if (table.configuration) {
return table.configuration.custom_root_fields;
}
return {};
};
export const getTableCustomColumnNames = table => {
if (table.configuration) {
return table.configuration.custom_column_names;
}
return {};
};

View File

@ -23,3 +23,19 @@ export const getDropPermissionQuery = (action, tableDef, role) => {
},
};
};
export const getSetCustomRootFieldsQuery = (
tableDef,
rootFields,
customColumnNames
) => {
return {
type: 'set_table_custom_fields',
version: 2,
args: {
table: tableDef,
custom_root_fields: rootFields,
custom_column_names: customColumnNames,
},
};
};

View File

@ -1,6 +1,7 @@
import React from 'react';
import Toggle from 'react-toggle';
import styles from '../../../../Common/Common.scss';
import ToolTip from '../../../../Common/Tooltip/Tooltip';
const enumCompatibilityDocsUrl =
'https://docs.hasura.io/1.0/graphql/manual/schema/enums.html#create-enum-table';
@ -53,15 +54,19 @@ const EnumsSection = ({ isEnum, toggleEnum, loading }) => {
return (
<div>
<h4 className={`${styles.subheading_text}`}>Set table as enum</h4>
<h4 className={`${styles.subheading_text}`}>
Set table as enum
<ToolTip
message={
'Expose the table values as GraphQL enums in the GraphQL API'
}
/>
</h4>
<div
className={`${styles.display_flex} ${styles.add_mar_bottom}`}
title={title}
data-toggle="tooltip"
>
<span className={styles.add_mar_right_mid}>
Expose the table values as GraphQL enums
</span>
<Toggle checked={isEnum} icons={false} onChange={toggleEnum} />
</div>
{getCompatibilityNote()}

View File

@ -0,0 +1,90 @@
import React from 'react';
import styles from '../../../../Common/Common.scss';
import { getRootFieldLabel } from './utils';
import CollapsibleToggle from '../../../../Common/CollapsibleToggle/CollapsibleToggle';
const RootFieldEditor = ({
rootFields,
disabled,
selectOnChange,
selectByPkOnChange,
selectAggOnChange,
insertOnChange,
updateOnChange,
deleteOnChange,
tableName,
}) => {
const {
select,
select_by_pk: selectByPk,
select_aggregate: selectAgg,
insert,
update,
delete: _delete,
} = rootFields;
const getDefaultRootField = rfType => {
if (rfType.includes('select')) {
return rfType.replace('select', tableName);
}
return `${rfType}_${tableName}`;
};
const getRow = (rfType, value, onChange) => (
<div
className={`${styles.display_flex} row ${styles.add_mar_bottom_small}`}
>
<div className={`${styles.add_mar_right} col-md-3`}>
{getRootFieldLabel(rfType)}
</div>
<div className={'col-md-5'}>
<input
type="text"
value={value || ''}
placeholder={`${getDefaultRootField(rfType)} (default)`}
className="form-control"
onChange={onChange}
disabled={disabled}
/>
</div>
</div>
);
const getSection = rfType => {
return (
<div className={`${styles.add_mar_bottom_mid}`}>
<CollapsibleToggle
title={rfType === 'query' ? 'Query and Subscription' : 'Mutation'}
useDefaultTitleStyle
isOpen
>
{rfType === 'query' && (
<div className={`${styles.add_pad_left} ${styles.add_pad_right}`}>
{getRow('select', select, selectOnChange)}
{getRow('select_by_pk', selectByPk, selectByPkOnChange)}
{getRow('select_aggregate', selectAgg, selectAggOnChange)}
</div>
)}
{rfType === 'mutation' && (
<div className={`${styles.add_pad_left} ${styles.add_pad_right}`}>
{getRow('insert', insert, insertOnChange)}
{getRow('update', update, updateOnChange)}
{getRow('delete', _delete, deleteOnChange)}
</div>
)}
</CollapsibleToggle>
</div>
);
};
return (
<div>
<div className={styles.add_mar_bottom_mid}>
{getSection('query')}
{getSection('mutation')}
</div>
</div>
);
};
export default RootFieldEditor;

View File

@ -117,3 +117,15 @@ export const getKeyDef = (config, constraintName) => {
</div>
);
};
export const getRootFieldLabel = rfType => {
const labels = {
select: 'Select',
select_by_pk: 'Select by PK',
select_aggregate: 'Select Aggregate',
insert: 'Insert',
update: 'Update',
delete: 'Delete',
};
return labels[rfType];
};

View File

@ -126,6 +126,14 @@ const defaultModifyState = {
colMappings: [{ column: '', refColumn: '' }],
isToggled: false,
},
rootFieldsEdit: {
select: '',
select_by_pk: '',
select_aggregate: '',
insert: '',
update: '',
delete: '',
},
permissionsState: { ...defaultPermissionsState },
prevPermissionState: { ...defaultPermissionsState },
ongoingRequest: false,

View File

@ -25,6 +25,7 @@ import {
TOGGLE_ENUM,
TOGGLE_ENUM_SUCCESS,
TOGGLE_ENUM_FAILURE,
MODIFY_ROOT_FIELD,
} from '../TableModify/ModifyActions';
// TABLE RELATIONSHIPS
@ -606,6 +607,11 @@ const modifyReducer = (tableName, schemas, modifyStateOrig, action) => {
loading: false,
},
};
case MODIFY_ROOT_FIELD:
return {
...modifyState,
rootFieldsEdit: action.data,
};
default:
return modifyState;
}

View File

@ -4,6 +4,11 @@ import SearchableSelectBox from '../../../Common/SearchableSelect/SearchableSele
import CustomInputAutoSuggest from '../../../Common/CustomInputAutoSuggest/CustomInputAutoSuggest';
import { getValidAlterOptions } from './utils';
import Tooltip from '../../../Common/Tooltip/Tooltip';
import {
checkFeatureSupport,
CUSTOM_GRAPHQL_FIELDS_SUPPORT,
} from '../../../../helpers/versionUtils';
const ColumnEditor = ({
onSubmit,
@ -57,18 +62,47 @@ const ColumnEditor = ({
const updateColumnType = selected => {
dispatch(editColumn(colName, 'type', selected.value));
};
const updateColumnDef = (e, data) => {
const toggleColumnNullable = e => {
dispatch(editColumn(colName, 'isNullable', e.target.value === 'true'));
};
const toggleColumnUnique = e => {
dispatch(editColumn(colName, 'isUnique', e.target.value === 'true'));
};
const updateColumnDefault = (e, data) => {
const { newValue } = data;
dispatch(editColumn(colName, 'default', newValue));
};
const updateColumnComment = e => {
dispatch(editColumn(colName, 'comment', e.target.value));
};
const toggleColumnNullable = e => {
dispatch(editColumn(colName, 'isNullable', e.target.value === 'true'));
const updateColumnCustomField = e => {
dispatch(editColumn(colName, 'customFieldName', e.target.value));
};
const toggleColumnUnique = e => {
dispatch(editColumn(colName, 'isUnique', e.target.value === 'true'));
const getColumnCustomFieldInput = () => {
if (!checkFeatureSupport(CUSTOM_GRAPHQL_FIELDS_SUPPORT)) return;
return (
<div className={`${styles.display_flex} form-group`}>
<label className={'col-xs-4'}>
Custom GraphQL field
<Tooltip
message={
'Expose the column with a different name in the GraphQL API'
}
/>
</label>
<div className="col-xs-6">
<input
className="input-sm form-control"
value={selectedProperties[colName].customFieldName}
onChange={updateColumnCustomField}
type="text"
data-test="edit-col-custom-field"
/>
</div>
</div>
);
};
const getColumnDefaultInput = () => {
@ -79,7 +113,7 @@ const ColumnEditor = ({
options={defaultOptions}
className="input-sm form-control"
value={selectedProperties[colName].default || ''}
onChange={updateColumnDef}
onChange={updateColumnDefault}
type="text"
disabled={columnProperties.pkConstraint}
data-test="edit-col-default"
@ -92,7 +126,7 @@ const ColumnEditor = ({
<div className={`${styles.colEditor} container-fluid`}>
<form className="form-horizontal" onSubmit={onSubmit}>
<div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Name</label>
<label className={'col-xs-4'}>Name</label>
<div className="col-xs-6">
<input
className="input-sm form-control"
@ -104,7 +138,7 @@ const ColumnEditor = ({
</div>
</div>
<div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Type</label>
<label className={'col-xs-4'}>Type</label>
<div className="col-xs-6">
<SearchableSelectBox
options={alterOptions}
@ -118,7 +152,7 @@ const ColumnEditor = ({
</div>
</div>
<div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Nullable</label>
<label className={'col-xs-4'}>Nullable</label>
<div className="col-xs-6">
<select
className="input-sm form-control"
@ -133,7 +167,7 @@ const ColumnEditor = ({
</div>
</div>
<div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Unique</label>
<label className={'col-xs-4'}>Unique</label>
<div className="col-xs-6">
<select
className="input-sm form-control"
@ -148,11 +182,11 @@ const ColumnEditor = ({
</div>
</div>
<div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Default</label>
<label className={'col-xs-4'}>Default</label>
<div className="col-xs-6">{getColumnDefaultInput()}</div>
</div>
<div className={`${styles.display_flex} form-group`}>
<label className="col-xs-2">Comment</label>
<label className={'col-xs-4'}>Comment</label>
<div className="col-xs-6">
<input
className="input-sm form-control"
@ -163,6 +197,7 @@ const ColumnEditor = ({
/>
</div>
</div>
{getColumnCustomFieldInput()}
</form>
<div className="row">
<br />

View File

@ -22,6 +22,10 @@ import GqlCompatibilityWarning from '../../../Common/GqlCompatibilityWarning/Gql
import styles from './ModifyTable.scss';
import { getConfirmation } from '../../../Common/utils/jsUtils';
import {
checkFeatureSupport,
CUSTOM_GRAPHQL_FIELDS_SUPPORT,
} from '../../../../helpers/versionUtils';
const ColumnEditorList = ({
tableSchema,
@ -31,6 +35,7 @@ const ColumnEditorList = ({
validTypeCasts,
dataTypeIndexMap,
columnDefaultFunctions,
customColumnNames,
}) => {
const tableName = tableSchema.table_name;
@ -79,6 +84,10 @@ const ColumnEditorList = ({
comment: col.comment || '',
};
if (checkFeatureSupport(CUSTOM_GRAPHQL_FIELDS_SUPPORT)) {
columnProperties.customFieldName = customColumnNames[colName] || '';
}
const onSubmit = toggleEditor => {
dispatch(saveColumnChangesSql(colName, col, toggleEditor));
};
@ -148,7 +157,14 @@ const ColumnEditorList = ({
const collapsedLabel = () => {
return (
<div key={colName}>
<b>{colName}</b> {gqlCompatibilityWarning()} - {keyProperties()}
<b>
{colName}
<i>
{columnProperties.customFieldName &&
`${columnProperties.customFieldName}`}
</i>
</b>{' '}
{gqlCompatibilityWarning()} - {keyProperties()}
</div>
);
};
@ -199,9 +215,9 @@ const ColumnEditorList = ({
* "Data type",
* "User friendly name of the data type",
* "Description of the data type",
* "Comma seperated castable data types",
* "Comma seperated user friendly names of the castable data types",
* "Colon seperated user friendly description of the castable data types"
* "Comma separated castable data types",
* "Comma separated user friendly names of the castable data types",
* "Colon separated user friendly description of the castable data types"
* ]
* */

View File

@ -1,5 +1,6 @@
import requestAction from '../../../../utils/requestAction';
import Endpoints, { globalCookiePolicy } from '../../../../Endpoints';
import { CLI_CONSOLE_MODE } from '../../../../constants';
import {
updateSchemaInfo,
handleMigrationErrors,
@ -34,15 +35,22 @@ import {
generateTableDef,
getTableCheckConstraints,
findTableCheckConstraint,
getTableCustomRootFields,
getTableCustomColumnNames,
} from '../../../Common/utils/pgUtils';
import { getSetCustomRootFieldsQuery } from '../../../Common/utils/v1QueryUtils';
import {
fetchColumnCastsQuery,
convertArrayToJson,
getCreatePkSql,
getDropPkSql,
sanitiseRootFields,
} from './utils';
import { CLI_CONSOLE_MODE } from '../../../../constants';
import {
checkFeatureSupport,
CUSTOM_GRAPHQL_FIELDS_SUPPORT,
} from '../../../../helpers/versionUtils';
const DELETE_PK_WARNING =
'Without a primary key there is no way to uniquely identify a row of a table';
@ -77,6 +85,9 @@ const TOGGLE_ENUM = 'ModifyTable/TOGGLE_ENUM';
const TOGGLE_ENUM_SUCCESS = 'ModifyTable/TOGGLE_ENUM_SUCCESS';
const TOGGLE_ENUM_FAILURE = 'ModifyTable/TOGGLE_ENUM_FAILURE';
export const MODIFY_ROOT_FIELD = 'ModifyTable/MODIFY_ROOT_FIELD';
const SET_CUSTOM_ROOT_FIELDS = 'ModifyTable/SET_CUSTOM_ROOT_FIELDS';
const RESET = 'ModifyTable/RESET';
const toggleEnumSuccess = () => ({
@ -92,6 +103,11 @@ const setForeignKeys = fks => ({
fks,
});
const modifyRootFields = rootFields => ({
type: MODIFY_ROOT_FIELD,
data: rootFields,
});
const editColumn = (column, key, value) => ({
type: EDIT_COLUMN,
column,
@ -134,6 +150,61 @@ const resetPrimaryKeys = () => ({
type: RESET_PRIMARY_KEY,
});
export const setCustomRootFields = successCb => (dispatch, getState) => {
const {
allSchemas: allTables,
currentTable: tableName,
currentSchema: schemaName,
modify: { rootFieldsEdit: newRootFields },
} = getState().tables;
dispatch({ type: SET_CUSTOM_ROOT_FIELDS });
const tableDef = generateTableDef(tableName, schemaName);
const table = findTable(allTables, tableDef);
const existingRootFields = getTableCustomRootFields(table);
const existingCustomColumnNames = getTableCustomColumnNames(table);
const upQuery = getSetCustomRootFieldsQuery(
tableDef,
sanitiseRootFields(newRootFields),
existingCustomColumnNames
);
const downQuery = getSetCustomRootFieldsQuery(
tableDef,
existingRootFields,
existingCustomColumnNames
);
const migrationName = `set_custom_root_fields_${schemaName}_${tableName}`;
const requestMsg = 'Setting custom root fields...';
const successMsg = 'Setting custom root fields successful';
const errorMsg = 'Setting custom root fields failed';
const customOnSuccess = () => {
if (successCb) {
successCb();
}
};
const customOnError = err => {
dispatch({ type: UPDATE_MIGRATION_STATUS_ERROR, data: err });
};
makeMigrationCall(
dispatch,
getState,
[upQuery],
[downQuery],
migrationName,
customOnSuccess,
customOnError,
requestMsg,
successMsg,
errorMsg
);
};
export const removeCheckConstraint = constraintName => (dispatch, getState) => {
const confirmMessage = `This will permanently delete the check constraint "${constraintName}" from this table`;
const isOk = getConfirmation(confirmMessage, true, constraintName);
@ -1463,6 +1534,7 @@ const saveColumnChangesSql = (colName, column, onSuccess) => {
const comment = columnEdit.comment || '';
const newName = columnEdit.name;
const currentSchema = columnEdit.schemaName;
const customFieldName = columnEdit.customFieldName;
const checkIfFunctionFormat = isPostgresFunction(def);
// ALTER TABLE <table> ALTER COLUMN <column> TYPE <column_type>;
let defWithQuotes;
@ -1471,18 +1543,16 @@ const saveColumnChangesSql = (colName, column, onSuccess) => {
} else {
defWithQuotes = def;
}
const tableDef = generateTableDef(tableName, currentSchema);
const table = findTable(getState().tables.allSchemas, tableDef);
// check if column type has changed before making it part of the migration
const originalColType = column.data_type; // "value"
const originalColDefault = column.column_default; // null or "value"
const originalColComment = column.comment; // null or "value"
const originalColNullable = column.is_nullable; // "YES" or "NO"
const originalColUnique = isColumnUnique(
getState().tables.allSchemas.find(
table =>
table.table_name === tableName && table.table_schema === currentSchema
),
colName
);
const originalColUnique = isColumnUnique(table, colName);
/* column type up/down migration */
const columnChangesUpQuery =
@ -1540,6 +1610,41 @@ const saveColumnChangesSql = (colName, column, onSuccess) => {
]
: [];
/* column custom field up/down migration*/
if (checkFeatureSupport(CUSTOM_GRAPHQL_FIELDS_SUPPORT)) {
const existingCustomColumnNames = getTableCustomColumnNames(table);
const existingRootFields = getTableCustomRootFields(table);
const newCustomColumnNames = { ...existingCustomColumnNames };
let isCustomFieldNameChanged = false;
if (customFieldName) {
if (customFieldName !== existingCustomColumnNames[colName]) {
isCustomFieldNameChanged = true;
newCustomColumnNames[colName] = customFieldName.trim();
}
} else {
if (existingCustomColumnNames[colName]) {
isCustomFieldNameChanged = true;
delete newCustomColumnNames[colName];
}
}
if (isCustomFieldNameChanged) {
schemaChangesUp.push(
getSetCustomRootFieldsQuery(
tableDef,
existingRootFields,
newCustomColumnNames
)
);
schemaChangesDown.push(
getSetCustomRootFieldsQuery(
tableDef,
existingRootFields,
existingCustomColumnNames
)
);
}
}
/* column default up/down migration */
if (def.trim() !== '') {
// ALTER TABLE ONLY <table> ALTER COLUMN <column> SET DEFAULT <default>;
@ -2381,4 +2486,5 @@ export {
deleteTrigger,
toggleEnumSuccess,
toggleEnumFailure,
modifyRootFields,
};

View File

@ -4,7 +4,11 @@ import TableHeader from '../TableCommon/TableHeader';
import { getAllDataTypeMap } from '../Common/utils';
import { TABLE_ENUMS_SUPPORT } from '../../../../helpers/versionUtils';
import {
checkFeatureSupport,
CUSTOM_GRAPHQL_FIELDS_SUPPORT,
TABLE_ENUMS_SUPPORT,
} from '../../../../helpers/versionUtils';
import globals from '../../../../Globals';
import {
@ -31,6 +35,7 @@ import ForeignKeyEditor from './ForeignKeyEditor';
import UniqueKeyEditor from './UniqueKeyEditor';
import TriggerEditorList from './TriggerEditorList';
import CheckConstraints from './CheckConstraints';
import RootFields from './RootFields';
import styles from './ModifyTable.scss';
import { NotFoundError } from '../../../Error/PageNotFound';
@ -39,7 +44,10 @@ import {
getTableCheckConstraints,
findTable,
generateTableDef,
getTableCustomRootFields,
getTableCustomColumnNames,
} from '../../../Common/utils/pgUtils';
import Tooltip from '../../../Common/Tooltip/Tooltip';
class ModifyTable extends React.Component {
componentDidMount() {
@ -48,11 +56,13 @@ class ModifyTable extends React.Component {
dispatch(setTable(this.props.tableName));
dispatch(fetchColumnTypeInfo());
}
componentWillUnmount() {
this.props.dispatch({
type: RESET_COLUMN_TYPE_INFO,
});
}
render() {
const {
tableName,
@ -70,6 +80,7 @@ class ModifyTable extends React.Component {
columnDefaultFunctions,
schemaList,
tableEnum,
rootFieldsEdit,
} = this.props;
const dataTypeIndexMap = getAllDataTypeMap(dataTypes);
@ -144,6 +155,33 @@ class ModifyTable extends React.Component {
};
// if (table.primary_key.columns > 0) {}
const getTableRootFieldsSection = () => {
if (!checkFeatureSupport(CUSTOM_GRAPHQL_FIELDS_SUPPORT)) return null;
const existingRootFields = getTableCustomRootFields(table);
return (
<React.Fragment>
<h4 className={styles.subheading_text}>
Custom GraphQL Root Fields
<Tooltip
message={
'Change the root fields for the table in the GraphQL API'
}
/>
</h4>
<RootFields
existingRootFields={existingRootFields}
rootFieldsEdit={rootFieldsEdit}
dispatch={dispatch}
tableName={tableName}
/>
<hr />
</React.Fragment>
);
};
// if (tableSchema.primary_key.columns > 0) {}
return (
<div className={`${styles.container} container-fluid`}>
<TableHeader
@ -177,6 +215,7 @@ class ModifyTable extends React.Component {
dispatch={dispatch}
currentSchema={currentSchema}
columnDefaultFunctions={columnDefaultFunctions}
customColumnNames={getTableCustomColumnNames(table)}
/>
<hr />
<h4 className={styles.subheading_text}>Add a new column</h4>
@ -225,6 +264,7 @@ class ModifyTable extends React.Component {
dispatch={dispatch}
/>
<hr />
{getTableRootFieldsSection()}
{getEnumsSection()}
{untrackBtn}
{deleteBtn}

View File

@ -0,0 +1,97 @@
import React from 'react';
import ExpandableEditor from '../../../Common/Layout/ExpandableEditor/Editor';
import RootFieldEditor from '../Common/ReusableComponents/RootFieldEditor';
import { modifyRootFields, setCustomRootFields } from './ModifyActions';
import { isEmpty } from '../../../Common/utils/jsUtils';
import styles from './ModifyTable.scss';
const RootFields = ({
existingRootFields,
rootFieldsEdit,
dispatch,
tableName,
}) => {
const setRootFieldsBulk = rf => {
dispatch(modifyRootFields(rf));
};
const onChange = (field, customField) => {
const newRootFields = {
...rootFieldsEdit,
[field]: customField,
};
dispatch(modifyRootFields(newRootFields));
};
const collapsedLabel = () => {
const customRootFieldLabels = [];
Object.keys(existingRootFields).forEach(rootField => {
const customRootField = existingRootFields[rootField];
if (customRootField) {
customRootFieldLabels.push(
<React.Fragment>
{!isEmpty(customRootFieldLabels) && ', '}
<span className={styles.display_inline} key={rootField}>
<i>{rootField}</i> &rarr; {customRootField}
</span>
</React.Fragment>
);
}
});
if (isEmpty(customRootFieldLabels)) {
customRootFieldLabels.push('No root fields customised');
}
return <span>{customRootFieldLabels}</span>;
};
const editorExpanded = () => (
<RootFieldEditor
tableName={tableName}
rootFields={rootFieldsEdit}
selectOnChange={e => {
onChange('select', e.target.value);
}}
selectByPkOnChange={e => {
onChange('select_by_pk', e.target.value);
}}
selectAggOnChange={e => {
onChange('select_aggregate', e.target.value);
}}
insertOnChange={e => {
onChange('insert', e.target.value);
}}
updateOnChange={e => {
onChange('update', e.target.value);
}}
deleteOnChange={e => {
onChange('delete', e.target.value);
}}
/>
);
const expandCallback = () => {
setRootFieldsBulk(existingRootFields);
};
const saveFunc = toggleEditor => {
dispatch(setCustomRootFields(toggleEditor));
};
return (
<ExpandableEditor
editorExpanded={editorExpanded}
expandCallback={expandCallback}
collapsedLabel={collapsedLabel}
saveFunc={saveFunc}
property="custom-root-fields"
service="modify-table"
isCollapsable
/>
);
};
export default RootFields;

View File

@ -85,6 +85,18 @@ const getDropPkSql = ({ schemaName, tableName, constraintName }) => {
return `alter table "${schemaName}"."${tableName}" drop constraint "${constraintName}";`;
};
export const sanitiseRootFields = rootFields => {
const santisedRootFields = {};
Object.keys(rootFields).forEach(rootFieldType => {
let rootField = rootFields[rootFieldType];
if (rootField !== null) {
rootField = rootField.trim() || null;
}
santisedRootFields[rootFieldType] = rootField;
});
return santisedRootFields;
};
export {
convertArrayToJson,
getValidAlterOptions,

View File

@ -1,5 +1,8 @@
import globals from '../../../Globals';
import { TABLE_ENUMS_SUPPORT } from '../../../helpers/versionUtils';
import {
TABLE_ENUMS_SUPPORT,
CUSTOM_GRAPHQL_FIELDS_SUPPORT,
checkFeatureSupport,
} from '../../../helpers/versionUtils';
export const INTEGER = 'integer';
export const SERIAL = 'serial';
@ -233,21 +236,22 @@ export const fetchTrackedTableListQuery = options => {
columns: ['*'],
order_by: {
column: 'constraint_name',
type: 'asc'
}
}
type: 'asc',
},
},
],
order_by: [{ column: 'table_name', type: 'asc' }],
},
};
const supportEnums =
globals.featuresCompatibility &&
globals.featuresCompatibility[TABLE_ENUMS_SUPPORT];
if (supportEnums) {
if (checkFeatureSupport(TABLE_ENUMS_SUPPORT)) {
query.args.columns.push('is_enum');
}
if (checkFeatureSupport(CUSTOM_GRAPHQL_FIELDS_SUPPORT)) {
query.args.columns.push('configuration');
}
if (
(options.schemas && options.schemas.length !== 0) ||
(options.tables && options.tables.length !== 0)
@ -490,6 +494,7 @@ export const mergeLoadSchemaData = (
let _refFkConstraints = [];
let _isEnum = false;
let _checkConstraints = [];
let _configuration = {};
if (_isTableTracked) {
_primaryKey = trackedTableInfo.primary_key;
@ -498,6 +503,7 @@ export const mergeLoadSchemaData = (
_uniqueConstraints = trackedTableInfo.unique_constraints;
_isEnum = trackedTableInfo.is_enum;
_checkConstraints = trackedTableInfo.check_constraints;
_configuration = trackedTableInfo.configuration;
_fkConstraints = fkData.filter(
fk => fk.table_schema === _tableSchema && fk.table_name === _tableName
@ -527,6 +533,7 @@ export const mergeLoadSchemaData = (
opp_foreign_key_constraints: _refFkConstraints,
view_info: _viewInfo,
is_enum: _isEnum,
configuration: _configuration,
};
_mergedTableData.push(_mergedInfo);

View File

@ -1,3 +1,5 @@
import globals from '../Globals';
const semver = require('semver');
export const FT_JWT_ANALYZER = 'JWTAnalyzer';
@ -6,6 +8,7 @@ export const REMOTE_SCHEMA_TIMEOUT_CONF_SUPPORT =
'remoteSchemaTimeoutConfSupport';
export const TABLE_ENUMS_SUPPORT = 'tableEnumsSupport';
export const EXISTS_PERMISSION_SUPPORT = 'existsPermissionSupport';
export const CUSTOM_GRAPHQL_FIELDS_SUPPORT = 'customGraphQLFieldsSupport';
export const COMPUTED_FIELDS_SUPPORT = 'computedFieldsSupport';
// list of feature launch versions
@ -16,6 +19,7 @@ const featureLaunchVersions = {
[REMOTE_SCHEMA_TIMEOUT_CONF_SUPPORT]: 'v1.0.0-beta.5',
[TABLE_ENUMS_SUPPORT]: 'v1.0.0-beta.6',
[EXISTS_PERMISSION_SUPPORT]: 'v1.0.0-beta.7',
[CUSTOM_GRAPHQL_FIELDS_SUPPORT]: 'v1.0.0-beta.8',
[COMPUTED_FIELDS_SUPPORT]: 'v1.0.0-beta.8',
};
@ -45,3 +49,9 @@ export const versionGT = (version1, version2) => {
return false;
}
};
export const checkFeatureSupport = feature => {
return (
globals.featuresCompatibility && globals.featuresCompatibility[feature]
);
};