Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dbfc9e2

Browse filesBrowse files
authored
misc console improvements (hasura#3435)
* persist rawSql content to LS * handle cleanup of admin secret related persisted info if admin secret is removed * show gql compatibility warning for invalid schemas and add to tooltip that types depending on the identifier will not be exposed over GraphQL * display non trackable functions section even if there are no functions * increase width of stack trace container on error page * fix PG version fetch query
1 parent f78518a commit dbfc9e2
Copy full SHA for dbfc9e2

File tree

Expand file treeCollapse file tree

15 files changed

+359
-324
lines changed
Filter options
Expand file treeCollapse file tree

15 files changed

+359
-324
lines changed

‎console/src/Globals.js

Copy file name to clipboardExpand all lines: console/src/Globals.js
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { SERVER_CONSOLE_MODE } from './constants';
22
import { getFeaturesCompatibility } from './helpers/versionUtils';
33
import { stripTrailingSlash } from './components/Common/utils/urlUtils';
4+
import { isEmpty } from './components/Common/utils/jsUtils';
45

56
// TODO: move this section to a more appropriate location
67
/* set helper tools into window */
@@ -29,7 +30,9 @@ const globals = {
2930
urlPrefix: stripTrailingSlash(window.__env.urlPrefix || '/'), // overridden below if server mode in production
3031
adminSecret: window.__env.adminSecret || null, // gets updated after login/logout in server mode
3132
isAdminSecretSet:
32-
window.__env.isAdminSecretSet || window.__env.adminSecret || false,
33+
window.__env.isAdminSecretSet ||
34+
!isEmpty(window.__env.adminSecret) ||
35+
false,
3336
consoleMode: window.__env.consoleMode || SERVER_CONSOLE_MODE,
3437
enableTelemetry: window.__env.enableTelemetry,
3538
telemetryTopic: isProduction ? 'console' : 'console_test',

‎console/src/components/Common/GqlCompatibilityWarning/GqlCompatibilityWarning.js

Copy file name to clipboardExpand all lines: console/src/components/Common/GqlCompatibilityWarning/GqlCompatibilityWarning.js
+17-3Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,25 @@ import React from 'react';
22

33
import WarningSymbol from '../WarningSymbol/WarningSymbol';
44

5-
const GqlCompatibilityWarning = () => {
5+
const gqlPattern = /^[_A-Za-z][_0-9A-Za-z]*$/;
6+
7+
const GqlCompatibilityWarning = ({ identifier, className = null }) => {
8+
const isGraphQLCompatible = gqlPattern.test(identifier);
9+
10+
if (isGraphQLCompatible) {
11+
return null;
12+
}
13+
614
const gqlCompatibilityTip =
7-
'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]*/.';
15+
'This identifier name does not conform to the GraphQL naming standard. ' +
16+
'Names in GraphQL should be limited to this ASCII subset: /[_A-Za-z][_0-9A-Za-z]*/. ' +
17+
'All GraphQL types depending on this identifier will not be exposed over the GraphQL API';
818

9-
return <WarningSymbol tooltipText={gqlCompatibilityTip} />;
19+
return (
20+
<span className={className}>
21+
<WarningSymbol tooltipText={gqlCompatibilityTip} />
22+
</span>
23+
);
1024
};
1125

1226
export default GqlCompatibilityWarning;

‎console/src/components/Common/utils/v1QueryUtils.js

Copy file name to clipboardExpand all lines: console/src/components/Common/utils/v1QueryUtils.js
+11-10Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
export const getRunSqlQuery = (sql, shouldCascade, readOnly) => {
2+
return {
3+
type: 'run_sql',
4+
args: {
5+
sql,
6+
cascade: !!shouldCascade,
7+
read_only: !!readOnly,
8+
},
9+
};
10+
};
11+
112
export const getCreatePermissionQuery = (
213
action,
314
tableDef,
@@ -39,13 +50,3 @@ export const getSetCustomRootFieldsQuery = (
3950
},
4051
};
4152
};
42-
43-
export const getRunSqlQuery = (sql, shouldCascade) => {
44-
return {
45-
type: 'run_sql',
46-
args: {
47-
sql,
48-
cascade: !!shouldCascade,
49-
},
50-
};
51-
};

‎console/src/components/Error/ErrorPage.scss

Copy file name to clipboardExpand all lines: console/src/components/Error/ErrorPage.scss
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
.errorStack {
3232
max-height: 300px;
33-
width: 450px;
33+
width: 95%;
3434
}
3535
}
3636
}

‎console/src/components/Services/About/About.js

Copy file name to clipboardExpand all lines: console/src/components/Services/About/About.js
+32-19Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import React, { Component } from 'react';
22
import Helmet from 'react-helmet';
33

4-
import Endpoints from '../../../Endpoints';
4+
import Endpoints, { globalCookiePolicy } from '../../../Endpoints';
55

66
import globals from '../../../Globals';
77

88
import styles from './About.scss';
9+
import requestAction from '../../../utils/requestAction';
10+
import { showErrorNotification } from '../Common/Notification';
11+
import { getRunSqlQuery } from '../../Common/utils/v1QueryUtils';
912

1013
class About extends Component {
1114
state = {
@@ -32,24 +35,32 @@ class About extends Component {
3235
})
3336
);
3437

35-
fetch(Endpoints.query, {
36-
method: 'POST',
37-
headers: {
38-
'Content-Type': 'application/json',
39-
},
40-
body: JSON.stringify({
41-
type: 'run_sql',
42-
args: {
43-
sql: 'SELECT version();',
38+
const fetchPgVersion = () => {
39+
const { dispatch, dataHeaders } = this.props;
40+
41+
const url = Endpoints.query;
42+
const options = {
43+
method: 'POST',
44+
credentials: globalCookiePolicy,
45+
headers: dataHeaders,
46+
body: JSON.stringify(getRunSqlQuery('SELECT version();', false, true)),
47+
};
48+
49+
dispatch(requestAction(url, options)).then(
50+
data => {
51+
this.setState({
52+
pgVersion: data.result[1][0],
53+
});
4454
},
45-
}),
46-
})
47-
.then(response => response.json())
48-
.then(data =>
49-
this.setState({
50-
pgVersion: data.result[1],
51-
})
55+
error => {
56+
dispatch(
57+
showErrorNotification('Failed fetching PG version', null, error)
58+
);
59+
}
5260
);
61+
};
62+
63+
fetchPgVersion();
5364
}
5465

5566
render() {
@@ -165,8 +176,10 @@ class About extends Component {
165176
}
166177
}
167178

168-
const mapStateToProps = () => {
169-
return {};
179+
const mapStateToProps = state => {
180+
return {
181+
dataHeaders: state.tables.dataHeaders,
182+
};
170183
};
171184

172185
const aboutConnector = connect => connect(mapStateToProps)(About);

‎console/src/components/Services/ApiExplorer/ApiRequest/ApiRequest.js

Copy file name to clipboardExpand all lines: console/src/components/Services/ApiExplorer/ApiRequest/ApiRequest.js
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
getAdminSecret,
3434
getPersistedAdminSecretHeaderWasAdded,
3535
persistAdminSecretHeaderWasAdded,
36+
removePersistedAdminSecretHeaderWasAdded,
3637
} from './utils';
3738

3839
import styles from '../ApiExplorer.scss';
@@ -90,6 +91,7 @@ class ApiRequest extends Component {
9091
if (adminSecret && !adminSecretHeaderWasAdded) {
9192
const headerKeys = graphiqlHeaders.map(h => h.key);
9293

94+
// add admin secret header if not present
9395
if (!headerKeys.includes(ADMIN_SECRET_HEADER_KEY)) {
9496
graphiqlHeaders.push({
9597
key: ADMIN_SECRET_HEADER_KEY,
@@ -104,6 +106,22 @@ class ApiRequest extends Component {
104106
persistAdminSecretHeaderWasAdded();
105107
}
106108

109+
// if admin secret is not set and admin secret header was ever added to headers, remove admin secret header if present
110+
if (!adminSecret && adminSecretHeaderWasAdded) {
111+
const headerKeys = graphiqlHeaders.map(h => h.key);
112+
113+
// remove admin secret header if present
114+
const adminSecretHeaderIndex = headerKeys.indexOf(
115+
ADMIN_SECRET_HEADER_KEY
116+
);
117+
if (adminSecretHeaderIndex >= 0) {
118+
graphiqlHeaders.splice(adminSecretHeaderIndex, 1);
119+
}
120+
121+
// remove from local storage that admin secret header has been automatically added
122+
removePersistedAdminSecretHeaderWasAdded();
123+
}
124+
107125
// add an empty placeholder header
108126
graphiqlHeaders.push({
109127
key: '',

‎console/src/components/Services/ApiExplorer/ApiRequest/utils.js

Copy file name to clipboardExpand all lines: console/src/components/Services/ApiExplorer/ApiRequest/utils.js
+14-6Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,26 @@ export const getAdminSecret = () => {
4747
return adminSecret;
4848
};
4949

50+
const LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED =
51+
'ApiExplorer:AdminSecretHeaderWasAdded';
52+
5053
export const persistAdminSecretHeaderWasAdded = () => {
51-
window.localStorage.setItem('ApiExplorer:AdminSecretHeaderWasAdded', true);
54+
window.localStorage.setItem(
55+
LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED,
56+
'true'
57+
);
5258
};
5359

54-
export const getPersistedAdminSecretHeaderWasAdded = () => {
55-
const defaultIsSet = false;
60+
export const removePersistedAdminSecretHeaderWasAdded = () => {
61+
window.localStorage.removeItem(LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED);
62+
};
5663

57-
const isSet = window.localStorage.getItem(
58-
'ApiExplorer:AdminSecretHeaderWasAdded'
64+
export const getPersistedAdminSecretHeaderWasAdded = () => {
65+
const lsValue = window.localStorage.getItem(
66+
LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED
5967
);
6068

61-
return isSet ? isSet === 'true' : defaultIsSet;
69+
return lsValue ? lsValue === 'true' : false;
6270
};
6371

6472
export const persistGraphiQLHeaders = headers => {

‎console/src/components/Services/Data/DataPageContainer.js

Copy file name to clipboardExpand all lines: console/src/components/Services/Data/DataPageContainer.js
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import globals from '../../../Globals';
55
import LeftContainer from '../../Common/Layout/LeftContainer/LeftContainer';
66
import PageContainer from '../../Common/Layout/PageContainer/PageContainer';
77
import DataSubSidebar from './DataSubSidebar';
8+
import GqlCompatibilityWarning from '../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning';
89

910
import { updateCurrentSchema } from './DataActions';
1011
import { NotFoundError } from '../../Error/PageNotFound';
@@ -77,6 +78,10 @@ const DataPageContainer = ({
7778
>
7879
{getSchemaOptions()}
7980
</select>
81+
<GqlCompatibilityWarning
82+
identifier={currentSchema}
83+
className={styles.add_mar_left_mid}
84+
/>
8085
</div>
8186
</div>
8287
</Link>

‎console/src/components/Services/Data/DataSubSidebar.js

Copy file name to clipboardExpand all lines: console/src/components/Services/Data/DataSubSidebar.js
+4-11Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { connect } from 'react-redux';
33
import { Link } from 'react-router';
44

55
import LeftSubSidebar from '../../Common/Layout/LeftSubSidebar/LeftSubSidebar';
6-
import gqlPattern from './Common/GraphQLValidation';
76
import GqlCompatibilityWarning from '../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning';
87
import {
98
displayTableName,
@@ -107,15 +106,6 @@ class DataSubSidebar extends React.Component {
107106
const isActive =
108107
tableName === currentTable && currentLocation.includes(tableName);
109108

110-
let gqlCompatibilityWarning = null;
111-
if (!gqlPattern.test(tableName)) {
112-
gqlCompatibilityWarning = (
113-
<span className={styles.add_mar_left_mid}>
114-
<GqlCompatibilityWarning />
115-
</span>
116-
);
117-
}
118-
119109
return (
120110
<li
121111
className={isActive ? styles.activeLink : ''}
@@ -135,7 +125,10 @@ class DataSubSidebar extends React.Component {
135125
/>
136126
{displayTableName(table)}
137127
</Link>
138-
{gqlCompatibilityWarning}
128+
<GqlCompatibilityWarning
129+
identifier={tableName}
130+
className={styles.add_mar_left_mid}
131+
/>
139132
</li>
140133
);
141134
});

‎console/src/components/Services/Data/RawSQL/RawSQL.js

Copy file name to clipboardExpand all lines: console/src/components/Services/Data/RawSQL/RawSQL.js
+33-3Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useEffect, useRef } from 'react';
22
import PropTypes from 'prop-types';
33
import Helmet from 'react-helmet';
44
import AceEditor from 'react-ace';
@@ -40,6 +40,32 @@ const RawSQL = ({
4040
}) => {
4141
const styles = require('../../../Common/TableCommon/Table.scss');
4242

43+
/* hooks */
44+
45+
// set up sqlRef to use in unmount
46+
const sqlRef = useRef(sql);
47+
48+
// set SQL from localStorage on mount and write back to localStorage on unmount
49+
useEffect(() => {
50+
const LS_RAW_SQL_SQL = 'rawSql:sql';
51+
52+
const sqlFromLocalStorage = localStorage.getItem(LS_RAW_SQL_SQL);
53+
if (sqlFromLocalStorage) {
54+
dispatch({ type: SET_SQL, data: sqlFromLocalStorage });
55+
}
56+
57+
return () => {
58+
localStorage.setItem(LS_RAW_SQL_SQL, sqlRef.current);
59+
};
60+
}, []);
61+
62+
// set SQL to sqlRef
63+
useEffect(() => {
64+
sqlRef.current = sql;
65+
}, [sql]);
66+
67+
/* hooks - end */
68+
4369
const cascadeTip = (
4470
<Tooltip id="tooltip-cascade">
4571
Cascade actions on all dependent metadata references, like relationships
@@ -252,7 +278,9 @@ const RawSQL = ({
252278
<h4 className={styles.subheading_text}>SQL Result:</h4>
253279
<div className={styles.tableContainer}>
254280
<table
255-
className={`table table-bordered table-striped table-hover ${styles.table} `}
281+
className={`table table-bordered table-striped table-hover ${
282+
styles.table
283+
} `}
256284
>
257285
<thead>
258286
<tr>{getTableHeadings()}</tr>
@@ -474,7 +502,9 @@ const RawSQL = ({
474502
</div>
475503

476504
<div
477-
className={`${styles.padd_left_remove} ${styles.add_mar_bottom} col-xs-8`}
505+
className={`${styles.padd_left_remove} ${
506+
styles.add_mar_bottom
507+
} col-xs-8`}
478508
>
479509
{getTrackThisSection()}
480510
{getMetadataCascadeSection()}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.