mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-11-11 05:10:51 +03:00
show warning for tables, columns, relationships which do not conform to GraphQL naming scheme (close #212) (#2422)
This commit is contained in:
parent
3445de3630
commit
4405bac577
@ -116,7 +116,7 @@ table thead tr th {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebarCreateTable {
|
||||
|
@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip';
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
|
||||
|
||||
import styles from './GqlCompatibilityWarning.scss';
|
||||
|
||||
const GqlCompatibilityWarning = () => {
|
||||
const gqlCompatibilityTip = (
|
||||
<Tooltip id="tooltip-scheme-warning">
|
||||
This identifier name does not conform to the GraphQL naming standard.
|
||||
Names in GraphQL should be limited to this ASCII subset:
|
||||
/[_A-Za-z][_0-9A-Za-z]*/.
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={styles.display_inline}>
|
||||
<OverlayTrigger placement="right" overlay={gqlCompatibilityTip}>
|
||||
<i
|
||||
className={`fa fa-exclamation-triangle ${
|
||||
styles.gqlCompatibilityWarning
|
||||
}`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</OverlayTrigger>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GqlCompatibilityWarning;
|
@ -0,0 +1,5 @@
|
||||
@import "../Common.scss";
|
||||
|
||||
.gqlCompatibilityWarning {
|
||||
color: #d9534f;
|
||||
}
|
@ -133,7 +133,7 @@
|
||||
|
||||
li {
|
||||
border-bottom: 0px !important;
|
||||
padding: 0 0 !important;
|
||||
padding: 4px 0 !important;
|
||||
|
||||
.tableFunctionDivider {
|
||||
margin-top: 5px;
|
||||
@ -146,6 +146,7 @@
|
||||
padding: 5px 0px !important;
|
||||
font-weight: 400 !important;
|
||||
padding-left: 5px !important;
|
||||
display: initial !important;
|
||||
|
||||
.tableIcon, .functionIcon {
|
||||
margin-right: 5px;
|
||||
|
@ -3,6 +3,8 @@ import { connect } from 'react-redux';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import LeftSubSidebar from '../../Common/Layout/LeftSubSidebar/LeftSubSidebar';
|
||||
import gqlPattern from './Common/GraphQLValidation';
|
||||
import GqlCompatibilityWarning from '../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning';
|
||||
|
||||
const appPrefix = '/data';
|
||||
|
||||
@ -101,6 +103,8 @@ class DataSubSidebar extends React.Component {
|
||||
tableLinks = Object.keys(tables)
|
||||
.sort()
|
||||
.map((tableName, i) => {
|
||||
let _childLink;
|
||||
|
||||
let activeTableClass = '';
|
||||
if (
|
||||
tableName === currentTable &&
|
||||
@ -108,8 +112,15 @@ class DataSubSidebar extends React.Component {
|
||||
) {
|
||||
activeTableClass = styles.activeTable;
|
||||
}
|
||||
|
||||
const gqlCompatibilityWarning = !gqlPattern.test(tableName) ? (
|
||||
<span className={styles.add_mar_left_mid}>
|
||||
<GqlCompatibilityWarning />
|
||||
</span>
|
||||
) : null;
|
||||
|
||||
if (tables[tableName].table_type === 'BASE TABLE') {
|
||||
return (
|
||||
_childLink = (
|
||||
<li className={activeTableClass} key={i}>
|
||||
<Link
|
||||
to={
|
||||
@ -128,31 +139,35 @@ class DataSubSidebar extends React.Component {
|
||||
/>
|
||||
{tableName}
|
||||
</Link>
|
||||
{gqlCompatibilityWarning}
|
||||
</li>
|
||||
);
|
||||
} else {
|
||||
_childLink = (
|
||||
<li className={activeTableClass} key={i}>
|
||||
<Link
|
||||
to={
|
||||
appPrefix +
|
||||
'/schema/' +
|
||||
currentSchema +
|
||||
'/views/' +
|
||||
tableName +
|
||||
'/browse'
|
||||
}
|
||||
data-test={tableName}
|
||||
>
|
||||
<i
|
||||
className={styles.tableIcon + ' fa fa-table'}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<i>{tableName}</i>
|
||||
</Link>
|
||||
{gqlCompatibilityWarning}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li className={activeTableClass} key={i}>
|
||||
<Link
|
||||
to={
|
||||
appPrefix +
|
||||
'/schema/' +
|
||||
currentSchema +
|
||||
'/views/' +
|
||||
tableName +
|
||||
'/browse'
|
||||
}
|
||||
data-test={tableName}
|
||||
>
|
||||
<i
|
||||
className={styles.tableIcon + ' fa fa-table'}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<i>{tableName}</i>
|
||||
</Link>
|
||||
</li>
|
||||
);
|
||||
return _childLink;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,8 @@ import globals from '../../../../Globals';
|
||||
import { getRelDef } from '../TableRelationships/utils';
|
||||
import { createNewSchema, deleteCurrentSchema } from './Actions';
|
||||
import CollapsibleToggle from '../../../Common/CollapsibleToggle/CollapsibleToggle';
|
||||
import gqlPattern from '../Common/GraphQLValidation';
|
||||
import GqlCompatibilityWarning from '../../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning';
|
||||
|
||||
const appPrefix = globals.urlPrefix + '/data';
|
||||
|
||||
@ -98,6 +100,11 @@ class Schema extends Component {
|
||||
table => !table.is_table_tracked && table.table_schema === currentSchema
|
||||
);
|
||||
|
||||
// update tableInfo with graphql compatibility
|
||||
_untrackedTables.forEach(t => {
|
||||
t.isGQLCompatible = gqlPattern.test(t.table_name);
|
||||
});
|
||||
|
||||
return _untrackedTables.sort(tableSortFunc);
|
||||
};
|
||||
|
||||
@ -317,6 +324,12 @@ class Schema extends Component {
|
||||
dispatch(addExistingTableSql());
|
||||
};
|
||||
|
||||
const gqlCompatibilityWarning = !table.isGQLCompatible ? (
|
||||
<span className={styles.add_mar_left_mid}>
|
||||
<GqlCompatibilityWarning />
|
||||
</span>
|
||||
) : null;
|
||||
|
||||
untrackedTablesList.push(
|
||||
<div className={styles.padd_bottom} key={`untracked-${i}`}>
|
||||
<div
|
||||
@ -333,6 +346,7 @@ class Schema extends Component {
|
||||
</Button>
|
||||
</div>
|
||||
<div className={styles.display_inline}>{table.table_name}</div>
|
||||
{gqlCompatibilityWarning}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -17,6 +17,9 @@ import {
|
||||
inferDefaultValues,
|
||||
} from '../Common/utils';
|
||||
|
||||
import gqlPattern from '../Common/GraphQLValidation';
|
||||
import GqlCompatibilityWarning from '../../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning';
|
||||
|
||||
import styles from './ModifyTable.scss';
|
||||
|
||||
const ColumnEditorList = ({
|
||||
@ -96,6 +99,14 @@ const ColumnEditorList = ({
|
||||
}
|
||||
};
|
||||
|
||||
const gqlCompatibilityWarning = () => {
|
||||
return !gqlPattern.test(colName) ? (
|
||||
<span className={styles.add_mar_left_small}>
|
||||
<GqlCompatibilityWarning />
|
||||
</span>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const keyProperties = () => {
|
||||
const propertiesDisplay = [];
|
||||
|
||||
@ -121,9 +132,7 @@ const ColumnEditorList = ({
|
||||
|
||||
const keyPropertiesString = propertiesList.join(', ');
|
||||
|
||||
propertiesDisplay.push(
|
||||
<i key={'props'}>{keyPropertiesString && `- ${keyPropertiesString}`}</i>
|
||||
);
|
||||
propertiesDisplay.push(<i key={'props'}>{keyPropertiesString}</i>);
|
||||
|
||||
propertiesDisplay.push(<br key={'br1'} />);
|
||||
|
||||
@ -139,7 +148,7 @@ const ColumnEditorList = ({
|
||||
const collapsedLabel = () => {
|
||||
return (
|
||||
<div key={colName}>
|
||||
<b>{colName}</b> {keyProperties()}
|
||||
<b>{colName}</b> {gqlCompatibilityWarning()} - {keyProperties()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -4,7 +4,10 @@ import Button from '../../../Common/Button/Button';
|
||||
import { deleteRelMigrate, saveRenameRelationship } from './Actions';
|
||||
import { showErrorNotification } from '../../Common/Notification';
|
||||
import gqlPattern, { gqlRelErrorNotif } from '../Common/GraphQLValidation';
|
||||
import GqlCompatibilityWarning from '../../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning';
|
||||
|
||||
import styles from '../TableModify/ModifyTable.scss';
|
||||
import tableStyles from '../../../Common/TableCommon/TableStyles.scss';
|
||||
|
||||
class RelationshipEditor extends React.Component {
|
||||
constructor(props) {
|
||||
@ -71,7 +74,11 @@ class RelationshipEditor extends React.Component {
|
||||
const { text, isEditting } = this.state;
|
||||
const { relName } = relConfig;
|
||||
|
||||
const tableStyles = require('../../../Common/TableCommon/TableStyles.scss');
|
||||
const gqlCompatibilityWarning = !gqlPattern.test(relName) ? (
|
||||
<span className={styles.add_mar_left_small}>
|
||||
<GqlCompatibilityWarning />
|
||||
</span>
|
||||
) : null;
|
||||
|
||||
const onDelete = e => {
|
||||
e.preventDefault();
|
||||
@ -91,7 +98,7 @@ class RelationshipEditor extends React.Component {
|
||||
Edit
|
||||
</Button>
|
||||
|
||||
<b>{relName}</b>
|
||||
<b>{relName}</b> {gqlCompatibilityWarning}
|
||||
<div className={tableStyles.relationshipTopPadding}>
|
||||
{getRelDef(relConfig)}
|
||||
</div>
|
||||
|
@ -623,29 +623,6 @@ GROUP BY t.typname
|
||||
ORDER BY t.typname ASC;
|
||||
`;
|
||||
|
||||
export const fetchTableTriggersSQL = (schema, table) => {
|
||||
return `
|
||||
select
|
||||
COALESCE(
|
||||
json_agg(
|
||||
row_to_json(t)
|
||||
),
|
||||
'[]' :: JSON
|
||||
) AS result FROM (
|
||||
select
|
||||
trigger_schema,
|
||||
trigger_name,
|
||||
event_manipulation,
|
||||
action_timing,
|
||||
action_statement,
|
||||
event_object_schema,
|
||||
event_object_table
|
||||
FROM information_schema.triggers
|
||||
WHERE event_object_schema = '${schema}' AND event_object_table = '${table}'
|
||||
) AS t
|
||||
`;
|
||||
};
|
||||
|
||||
const postgresFunctionTester = /.*\(\)$/gm;
|
||||
|
||||
export const isPostgresFunction = str =>
|
||||
|
Loading…
Reference in New Issue
Block a user