From b48b181817e980623fba9b2514b3152a9e1bf340 Mon Sep 17 00:00:00 2001 From: rikinsk Date: Tue, 26 Nov 2019 20:48:39 +0530 Subject: [PATCH 01/10] show non trackable functions section always --- .../components/Services/Data/Schema/Schema.js | 117 +++++++++--------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/console/src/components/Services/Data/Schema/Schema.js b/console/src/components/Services/Data/Schema/Schema.js index e5a9666e71dce..8516434d9fdf4 100644 --- a/console/src/components/Services/Data/Schema/Schema.js +++ b/console/src/components/Services/Data/Schema/Schema.js @@ -600,66 +600,71 @@ class Schema extends Component { }; const getNonTrackableFunctionsSection = () => { - let nonTrackableFuncList = null; + const noNonTrackableFuncs = isEmpty(nonTrackableFunctions); - if (nonTrackableFunctions.length > 0) { - const heading = getSectionHeading( - 'Non trackable functions', - nonTrackableFunctionsTip - ); + const getNonTrackableFuncList = () => { + const nonTrackableFunctionList = []; - nonTrackableFuncList = ( -
- -
-
- {getTrackableFunctionsRequirementsMessage()} -
- {nonTrackableFunctions.map((p, i) => ( -
-
- -
-
- {p.function_name} -
-
- ))} + nonTrackableFunctions.forEach((p, i) => { + nonTrackableFunctionList.push( +
+
+
-
- -
- ); - } +
{p.function_name}
+
+ ); + }); + + if (noNonTrackableFuncs) { + nonTrackableFunctionList.push( +
+
There are no non trackable functions
+
+ ); + } + + return nonTrackableFunctionList; + }; + + const heading = getSectionHeading( + 'Non trackable functions', + nonTrackableFunctionsTip + ); - return nonTrackableFuncList; + return ( +
+ +
+
+ {getTrackableFunctionsRequirementsMessage()} +
+ {getNonTrackableFuncList()} +
+
+ +
+ ); }; const getPermissionsSummaryLink = () => { From 23c7108356f5686f6651e1d2047b6a30729ead35 Mon Sep 17 00:00:00 2001 From: rikinsk Date: Wed, 27 Nov 2019 15:51:42 +0530 Subject: [PATCH 02/10] persist RawSQL SQL to localStorage --- .../components/Services/Data/RawSQL/RawSQL.js | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/console/src/components/Services/Data/RawSQL/RawSQL.js b/console/src/components/Services/Data/RawSQL/RawSQL.js index 98d8b00ec02bc..f842eb4980955 100644 --- a/console/src/components/Services/Data/RawSQL/RawSQL.js +++ b/console/src/components/Services/Data/RawSQL/RawSQL.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import AceEditor from 'react-ace'; @@ -40,6 +40,32 @@ const RawSQL = ({ }) => { const styles = require('../../../Common/TableCommon/Table.scss'); + /* hooks */ + + // set up sqlRef to use in unmount + const sqlRef = useRef(sql); + + // set SQL from localStorage on mount and write back to locallStorage on unmount + useEffect(() => { + const LS_RAW_SQL_SQL = 'rawSql:sql'; + + const sqlFromLocalStorage = localStorage.getItem(LS_RAW_SQL_SQL); + if (sqlFromLocalStorage) { + dispatch({ type: SET_SQL, data: sqlFromLocalStorage }); + } + + return () => { + localStorage.setItem(LS_RAW_SQL_SQL, sqlRef.current); + }; + }, []); + + // set SQL to sqlRef + useEffect(() => { + sqlRef.current = sql; + }, [sql]); + + /* hooks - end */ + const cascadeTip = ( Cascade actions on all dependent metadata references, like relationships @@ -252,7 +278,9 @@ const RawSQL = ({

SQL Result:

{getTableHeadings()} @@ -474,7 +502,9 @@ const RawSQL = ({
{getTrackThisSection()} {getMetadataCascadeSection()} From 58f98877de308e3b848d7369fb396af72c593d22 Mon Sep 17 00:00:00 2001 From: rikinsk Date: Wed, 27 Nov 2019 15:56:55 +0530 Subject: [PATCH 03/10] fix typo --- console/src/components/Services/Data/RawSQL/RawSQL.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/console/src/components/Services/Data/RawSQL/RawSQL.js b/console/src/components/Services/Data/RawSQL/RawSQL.js index f842eb4980955..c0ff9409119b0 100644 --- a/console/src/components/Services/Data/RawSQL/RawSQL.js +++ b/console/src/components/Services/Data/RawSQL/RawSQL.js @@ -45,7 +45,7 @@ const RawSQL = ({ // set up sqlRef to use in unmount const sqlRef = useRef(sql); - // set SQL from localStorage on mount and write back to locallStorage on unmount + // set SQL from localStorage on mount and write back to localStorage on unmount useEffect(() => { const LS_RAW_SQL_SQL = 'rawSql:sql'; From a0f57e34f4238240cc12f95a7fea09250b110ff9 Mon Sep 17 00:00:00 2001 From: rikinsk Date: Wed, 27 Nov 2019 18:33:02 +0530 Subject: [PATCH 04/10] handle admin secret removal on console --- console/src/Globals.js | 5 ++++- .../ApiExplorer/ApiRequest/ApiRequest.js | 18 +++++++++++++++++ .../Services/ApiExplorer/ApiRequest/utils.js | 20 +++++++++++++------ console/src/utils/validateLogin.js | 2 ++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/console/src/Globals.js b/console/src/Globals.js index ee4d8cd11a867..eaa8e21ec4816 100644 --- a/console/src/Globals.js +++ b/console/src/Globals.js @@ -1,6 +1,7 @@ import { SERVER_CONSOLE_MODE } from './constants'; import { getFeaturesCompatibility } from './helpers/versionUtils'; import { stripTrailingSlash } from './components/Common/utils/urlUtils'; +import { isEmpty } from './components/Common/utils/jsUtils'; // TODO: move this section to a more appropriate location /* set helper tools into window */ @@ -29,7 +30,9 @@ const globals = { urlPrefix: stripTrailingSlash(window.__env.urlPrefix || '/'), // overridden below if server mode in production adminSecret: window.__env.adminSecret || null, // gets updated after login/logout in server mode isAdminSecretSet: - window.__env.isAdminSecretSet || window.__env.adminSecret || false, + window.__env.isAdminSecretSet || + !isEmpty(window.__env.adminSecret) || + false, consoleMode: window.__env.consoleMode || SERVER_CONSOLE_MODE, enableTelemetry: window.__env.enableTelemetry, telemetryTopic: isProduction ? 'console' : 'console_test', diff --git a/console/src/components/Services/ApiExplorer/ApiRequest/ApiRequest.js b/console/src/components/Services/ApiExplorer/ApiRequest/ApiRequest.js index ea041fea824e8..8aba89048545e 100644 --- a/console/src/components/Services/ApiExplorer/ApiRequest/ApiRequest.js +++ b/console/src/components/Services/ApiExplorer/ApiRequest/ApiRequest.js @@ -33,6 +33,7 @@ import { getAdminSecret, getPersistedAdminSecretHeaderWasAdded, persistAdminSecretHeaderWasAdded, + removePersistedAdminSecretHeaderWasAdded, } from './utils'; import styles from '../ApiExplorer.scss'; @@ -90,6 +91,7 @@ class ApiRequest extends Component { if (adminSecret && !adminSecretHeaderWasAdded) { const headerKeys = graphiqlHeaders.map(h => h.key); + // add admin secret header if not present if (!headerKeys.includes(ADMIN_SECRET_HEADER_KEY)) { graphiqlHeaders.push({ key: ADMIN_SECRET_HEADER_KEY, @@ -104,6 +106,22 @@ class ApiRequest extends Component { persistAdminSecretHeaderWasAdded(); } + // if admin secret is not set and admin secret header was ever added to headers, remove admin secret header if present + if (!adminSecret && adminSecretHeaderWasAdded) { + const headerKeys = graphiqlHeaders.map(h => h.key); + + // remove admin secret header if present + const adminSecretHeaderIndex = headerKeys.indexOf( + ADMIN_SECRET_HEADER_KEY + ); + if (adminSecretHeaderIndex >= 0) { + graphiqlHeaders.splice(adminSecretHeaderIndex, 1); + } + + // remove from local storage that admin secret header has been automatically added + removePersistedAdminSecretHeaderWasAdded(); + } + // add an empty placeholder header graphiqlHeaders.push({ key: '', diff --git a/console/src/components/Services/ApiExplorer/ApiRequest/utils.js b/console/src/components/Services/ApiExplorer/ApiRequest/utils.js index d57ae40640aae..6c6a2f92f1386 100644 --- a/console/src/components/Services/ApiExplorer/ApiRequest/utils.js +++ b/console/src/components/Services/ApiExplorer/ApiRequest/utils.js @@ -47,18 +47,26 @@ export const getAdminSecret = () => { return adminSecret; }; +const LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED = + 'ApiExplorer:AdminSecretHeaderWasAdded'; + export const persistAdminSecretHeaderWasAdded = () => { - window.localStorage.setItem('ApiExplorer:AdminSecretHeaderWasAdded', true); + window.localStorage.setItem( + LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED, + 'true' + ); }; -export const getPersistedAdminSecretHeaderWasAdded = () => { - const defaultIsSet = false; +export const removePersistedAdminSecretHeaderWasAdded = () => { + window.localStorage.removeItem(LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED); +}; - const isSet = window.localStorage.getItem( - 'ApiExplorer:AdminSecretHeaderWasAdded' +export const getPersistedAdminSecretHeaderWasAdded = () => { + const lsValue = window.localStorage.getItem( + LS_API_EXPLORER_ADMIN_SECRET_HEADER_WAS_ADDED ); - return isSet ? isSet === 'true' : defaultIsSet; + return lsValue ? lsValue === 'true' : false; }; export const persistGraphiQLHeaders = headers => { diff --git a/console/src/utils/validateLogin.js b/console/src/utils/validateLogin.js index 549cc7fc0f314..1cef7d9a13bdb 100644 --- a/console/src/utils/validateLogin.js +++ b/console/src/utils/validateLogin.js @@ -37,6 +37,8 @@ const validateLogin = ({ dispatch }) => { dispatch, }); } else { + clearAdminSecretState(); + cb(); } }; From 36cbb691a61d40b8d258e1b545b6235d8cb6b07e Mon Sep 17 00:00:00 2001 From: rikinsk Date: Wed, 27 Nov 2019 20:08:09 +0530 Subject: [PATCH 05/10] show gql compatibility warning for schemas --- .../GqlCompatibilityWarning.js | 20 +++++++++-- .../Services/Data/DataSubSidebar.js | 17 +++++----- .../components/Services/Data/Schema/Schema.js | 33 +++++++++++++------ .../Data/TableModify/ColumnEditorList.js | 12 +++---- .../TableRelationships/RelationshipEditor.js | 15 +++++---- 5 files changed, 63 insertions(+), 34 deletions(-) diff --git a/console/src/components/Common/GqlCompatibilityWarning/GqlCompatibilityWarning.js b/console/src/components/Common/GqlCompatibilityWarning/GqlCompatibilityWarning.js index c52bffdea9f5e..2577ae8502a44 100644 --- a/console/src/components/Common/GqlCompatibilityWarning/GqlCompatibilityWarning.js +++ b/console/src/components/Common/GqlCompatibilityWarning/GqlCompatibilityWarning.js @@ -2,11 +2,25 @@ import React from 'react'; import WarningSymbol from '../WarningSymbol/WarningSymbol'; -const GqlCompatibilityWarning = () => { +const gqlPattern = /^[_A-Za-z][_0-9A-Za-z]*$/; + +const GqlCompatibilityWarning = ({ identifier, className = null }) => { + const isGraphQLCompatible = gqlPattern.test(identifier); + + if (isGraphQLCompatible) { + return null; + } + const gqlCompatibilityTip = - '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]*/.'; + '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]*/. ' + + 'All GraphQL types depending on this identifier will not be exposed over the GraphQL API'; - return ; + return ( + + + + ); }; export default GqlCompatibilityWarning; diff --git a/console/src/components/Services/Data/DataSubSidebar.js b/console/src/components/Services/Data/DataSubSidebar.js index d0928841dad59..960d87d31f01a 100644 --- a/console/src/components/Services/Data/DataSubSidebar.js +++ b/console/src/components/Services/Data/DataSubSidebar.js @@ -3,7 +3,6 @@ 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'; import { displayTableName, @@ -107,14 +106,14 @@ class DataSubSidebar extends React.Component { const isActive = tableName === currentTable && currentLocation.includes(tableName); - let gqlCompatibilityWarning = null; - if (!gqlPattern.test(tableName)) { - gqlCompatibilityWarning = ( - - - + const gqlCompatibilityWarning = () => { + return ( + ); - } + }; return (
  • {displayTableName(table)} - {gqlCompatibilityWarning} + {gqlCompatibilityWarning()}
  • ); }); diff --git a/console/src/components/Services/Data/Schema/Schema.js b/console/src/components/Services/Data/Schema/Schema.js index 8516434d9fdf4..b1ee38bc98e20 100644 --- a/console/src/components/Services/Data/Schema/Schema.js +++ b/console/src/components/Services/Data/Schema/Schema.js @@ -35,7 +35,6 @@ import { } from '../../../Common/utils/routesUtils'; import { createNewSchema, deleteCurrentSchema } from './Actions'; import CollapsibleToggle from '../../../Common/CollapsibleToggle/CollapsibleToggle'; -import gqlPattern from '../Common/GraphQLValidation'; import GqlCompatibilityWarning from '../../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning'; import { displayTableName, @@ -295,6 +294,15 @@ class Schema extends Component { return deleteSchemaBtn; }; + const gqlCompatibilityWarning = () => { + return ( + + ); + }; + return (
    Current Postgres schema
    @@ -312,6 +320,7 @@ class Schema extends Component { {getSchemaOptions()}
    + {gqlCompatibilityWarning()}
    {getDeleteSchemaBtn()}
    { + const tableName = table.table_name; + const handleTrackTable = e => { e.preventDefault(); - dispatch(setTableName(table.table_name)); + dispatch(setTableName(tableName)); dispatch(addExistingTableSql()); }; - const isGQLCompatible = gqlPattern.test(table.table_name); - const gqlCompatibilityWarning = !isGQLCompatible ? ( - - - - ) : null; + const gqlCompatibilityWarning = () => { + return ( + + ); + }; untrackedTablesList.push(
    @@ -382,7 +395,7 @@ class Schema extends Component { className={`${styles.display_inline} ${styles.add_mar_right}`} >
    - {gqlCompatibilityWarning} + {gqlCompatibilityWarning()}
    ); }); diff --git a/console/src/components/Services/Data/TableModify/ColumnEditorList.js b/console/src/components/Services/Data/TableModify/ColumnEditorList.js index 0d5b60fbe6c73..3b0914588ed34 100644 --- a/console/src/components/Services/Data/TableModify/ColumnEditorList.js +++ b/console/src/components/Services/Data/TableModify/ColumnEditorList.js @@ -17,7 +17,6 @@ import { inferDefaultValues, } from '../Common/utils'; -import gqlPattern from '../Common/GraphQLValidation'; import GqlCompatibilityWarning from '../../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning'; import styles from './ModifyTable.scss'; @@ -105,11 +104,12 @@ const ColumnEditorList = ({ }; const gqlCompatibilityWarning = () => { - return !gqlPattern.test(colName) ? ( - - - - ) : null; + return ( + + ); }; const keyProperties = () => { diff --git a/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js b/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js index be9974417a777..4610667e1c733 100644 --- a/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js +++ b/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js @@ -77,11 +77,14 @@ class RelationshipEditor extends React.Component { const { relName } = relConfig; - const gqlCompatibilityWarning = !gqlPattern.test(relName) ? ( - - - - ) : null; + const gqlCompatibilityWarning = () => { + return ( + + ); + }; const onDelete = e => { e.preventDefault(); @@ -103,7 +106,7 @@ class RelationshipEditor extends React.Component { Edit   - {relName} {gqlCompatibilityWarning} + {relName} {gqlCompatibilityWarning()}
    {getRelDef(relConfig)}
    From f3443872e1f4e81900638322da6e33d969a0785f Mon Sep 17 00:00:00 2001 From: rikinsk Date: Thu, 28 Nov 2019 14:11:35 +0530 Subject: [PATCH 06/10] refactor --- .../Services/Data/DataPageContainer.js | 5 ++++ .../Services/Data/DataSubSidebar.js | 14 ++++------- .../components/Services/Data/Schema/Schema.js | 24 ++++--------------- .../TableRelationships/RelationshipEditor.js | 15 ++++-------- 4 files changed, 18 insertions(+), 40 deletions(-) diff --git a/console/src/components/Services/Data/DataPageContainer.js b/console/src/components/Services/Data/DataPageContainer.js index cb5b98fb855a4..845af79e83362 100644 --- a/console/src/components/Services/Data/DataPageContainer.js +++ b/console/src/components/Services/Data/DataPageContainer.js @@ -5,6 +5,7 @@ import globals from '../../../Globals'; import LeftContainer from '../../Common/Layout/LeftContainer/LeftContainer'; import PageContainer from '../../Common/Layout/PageContainer/PageContainer'; import DataSubSidebar from './DataSubSidebar'; +import GqlCompatibilityWarning from '../../Common/GqlCompatibilityWarning/GqlCompatibilityWarning'; import { updateCurrentSchema } from './DataActions'; import { NotFoundError } from '../../Error/PageNotFound'; @@ -77,6 +78,10 @@ const DataPageContainer = ({ > {getSchemaOptions()} +
    diff --git a/console/src/components/Services/Data/DataSubSidebar.js b/console/src/components/Services/Data/DataSubSidebar.js index 960d87d31f01a..2851fcda2bb23 100644 --- a/console/src/components/Services/Data/DataSubSidebar.js +++ b/console/src/components/Services/Data/DataSubSidebar.js @@ -106,15 +106,6 @@ class DataSubSidebar extends React.Component { const isActive = tableName === currentTable && currentLocation.includes(tableName); - const gqlCompatibilityWarning = () => { - return ( - - ); - }; - return (
  • {displayTableName(table)} - {gqlCompatibilityWarning()} +
  • ); }); diff --git a/console/src/components/Services/Data/Schema/Schema.js b/console/src/components/Services/Data/Schema/Schema.js index b1ee38bc98e20..b98ba4a6017ac 100644 --- a/console/src/components/Services/Data/Schema/Schema.js +++ b/console/src/components/Services/Data/Schema/Schema.js @@ -294,15 +294,6 @@ class Schema extends Component { return deleteSchemaBtn; }; - const gqlCompatibilityWarning = () => { - return ( - - ); - }; - return (
    Current Postgres schema
    @@ -320,7 +311,6 @@ class Schema extends Component { {getSchemaOptions()}
    - {gqlCompatibilityWarning()}
    {getDeleteSchemaBtn()}
    { - return ( - - ); - }; - untrackedTablesList.push(
    {displayTableName(table)}
    - {gqlCompatibilityWarning()} +
    ); }); diff --git a/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js b/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js index 4610667e1c733..c17e1369329e6 100644 --- a/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js +++ b/console/src/components/Services/Data/TableRelationships/RelationshipEditor.js @@ -77,15 +77,6 @@ class RelationshipEditor extends React.Component { const { relName } = relConfig; - const gqlCompatibilityWarning = () => { - return ( - - ); - }; - const onDelete = e => { e.preventDefault(); @@ -106,7 +97,11 @@ class RelationshipEditor extends React.Component { Edit   - {relName} {gqlCompatibilityWarning()} + {relName} +
    {getRelDef(relConfig)}
    From b7149906d4bf5fc7a9081bf6d276765f18e4b2eb Mon Sep 17 00:00:00 2001 From: rikinsk Date: Thu, 28 Nov 2019 15:26:42 +0530 Subject: [PATCH 07/10] refactor --- .../components/Services/Data/Schema/Schema.js | 330 ++++++++---------- .../Services/Data/Schema/Tooltips.js | 28 -- 2 files changed, 152 insertions(+), 206 deletions(-) delete mode 100644 console/src/components/Services/Data/Schema/Tooltips.js diff --git a/console/src/components/Services/Data/Schema/Schema.js b/console/src/components/Services/Data/Schema/Schema.js index b98ba4a6017ac..68cc1cc31c93f 100644 --- a/console/src/components/Services/Data/Schema/Schema.js +++ b/console/src/components/Services/Data/Schema/Schema.js @@ -4,14 +4,6 @@ import Helmet from 'react-helmet'; import { push } from 'react-router-redux'; import { Link } from 'react-router'; -import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; - -import { - untrackedTablesTip, - untrackedRelTip, - trackableFunctionsTip, - nonTrackableFunctionsTip, -} from './Tooltips'; import Button from '../../../Common/Button/Button'; import { setTableName, @@ -46,6 +38,8 @@ import { SET_SQL } from '../RawSQL/Actions'; import _push from '../push'; import { isEmpty } from '../../../Common/utils/jsUtils'; import { getConfirmation } from '../../../Common/utils/jsUtils'; +import ToolTip from '../../../Common/Tooltip/Tooltip'; +import KnowMoreLink from '../../../Common/KnowMoreLink/KnowMoreLink'; class Schema extends Component { constructor(props) { @@ -100,20 +94,16 @@ class Schema extends Component { return functionsList.filter(filterCondition); }; - const getSectionHeading = (headingText, tooltip, actionBtn = null) => { + const getSectionHeading = (headingText, tooltip, actionElement = null) => { return (
    -

    +

    {headingText}

    - -