diff --git a/CHANGELOG.md b/CHANGELOG.md
index 198338168df..9ff6da16b5e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This release contains the [PDV refactor (#4111)](https://github.com/hasura/graph
- server: miscellaneous description changes (#4111)
- server: treat the absence of `backend_only` configuration and `backend_only: false` equally (closing #5059) (#4111)
- console: allow user to cascade Postgres dependencies when dropping Postgres objects (close #5109) (#5248)
+- console: mark inconsistent remote schemas in the UI (close #5093) (#5181)
- cli: add missing global flags for seeds command (#5565)
- docs: add docs page on networking with docker (close #4346) (#4811)
diff --git a/console/src/components/Common/Layout/LeftSubSidebar/LeftSubSidebar.scss b/console/src/components/Common/Layout/LeftSubSidebar/LeftSubSidebar.scss
index 13a82bf274a..05ede99cc4a 100644
--- a/console/src/components/Common/Layout/LeftSubSidebar/LeftSubSidebar.scss
+++ b/console/src/components/Common/Layout/LeftSubSidebar/LeftSubSidebar.scss
@@ -1,5 +1,5 @@
-@import "~bootstrap-sass/assets/stylesheets/bootstrap/variables";
-@import "../../Common.scss";
+@import '~bootstrap-sass/assets/stylesheets/bootstrap/variables';
+@import '../../Common.scss';
.container {
}
@@ -28,8 +28,8 @@
// background: #444;
// color: $navbar-inverse-color;
color: #333;
- border: 1px solid #E5E5E5;
- background-color: #F8F8F8;
+ border: 1px solid #e5e5e5;
+ background-color: #f8f8f8;
/*
a,a:visited {
@@ -66,7 +66,7 @@
*/
a {
- color: #767E93;
+ color: #767e93;
word-wrap: break-word;
}
}
@@ -75,9 +75,9 @@
padding: 7px 0;
// color: $navbar-inverse-link-hover-color;
transition: color 0.5s;
- pointer: cursor;
+ cursor: pointer;
}
- }
+ }
}
.main {
@@ -113,7 +113,7 @@
.sidebarHeading {
font-weight: bold;
display: inline-block;
- color: #767E93;
+ color: #767e93;
font-size: 15px;
}
}
@@ -148,19 +148,23 @@
padding-left: 5px !important;
display: initial !important;
- .tableIcon, .functionIcon {
- //display: inline;
+ .tableIcon,
+ .functionIcon {
margin-right: 5px;
font-size: 12px;
width: 12px;
}
+
+ .icon_mar_left {
+ margin-left: 5px;
+ }
}
}
.noChildren {
font-weight: 400 !important;
padding-bottom: 10px !important;
- color: #767E93 !important;
+ color: #767e93 !important;
}
li:first-child {
@@ -170,11 +174,16 @@
.activeLink {
a {
- // border-left: 4px solid #FFC627;
- color: #FD9540!important;
+ color: #fd9540 !important;
}
}
+.padLeft4 {
+ margin-left: 8px;
+ top: 12px;
+ font-size: 14px;
+}
+
.floatRight {
float: right;
margin-right: 20px;
diff --git a/console/src/components/Services/RemoteSchema/Actions.js b/console/src/components/Services/RemoteSchema/Actions.js
index ab99bcdea20..57b8f286037 100644
--- a/console/src/components/Services/RemoteSchema/Actions.js
+++ b/console/src/components/Services/RemoteSchema/Actions.js
@@ -1,7 +1,4 @@
-/* */
import { listState } from './state';
-/* */
-
import Endpoints, { globalCookiePolicy } from '../../../Endpoints';
import requestAction from '../../../utils/requestAction';
import dataHeaders from '../Data/Common/Headers';
@@ -10,9 +7,7 @@ import returnMigrateUrl from '../Data/Common/getMigrateUrl';
import { CLI_CONSOLE_MODE, SERVER_CONSOLE_MODE } from '../../../constants';
import { loadMigrationStatus } from '../../Main/Actions';
import { handleMigrationErrors } from '../../../utils/migration';
-
import { showSuccessNotification } from '../Common/Notification';
-import { filterInconsistentMetadataObjects } from '../Settings/utils';
/* Action constants */
@@ -51,20 +46,9 @@ const fetchRemoteSchemas = () => {
dispatch({ type: FETCH_REMOTE_SCHEMAS });
return dispatch(requestAction(url, options)).then(
data => {
- let consistentRemoteSchemas = data;
- const { inconsistentObjects } = getState().metadata;
-
- if (inconsistentObjects.length > 0) {
- consistentRemoteSchemas = filterInconsistentMetadataObjects(
- data,
- inconsistentObjects,
- 'remote_schemas'
- );
- }
-
dispatch({
type: REMOTE_SCHEMAS_FETCH_SUCCESS,
- data: consistentRemoteSchemas,
+ data,
});
return Promise.resolve();
},
diff --git a/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js b/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js
index ecd7693f2f3..39bc6b472bd 100644
--- a/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js
+++ b/console/src/components/Services/RemoteSchema/Add/addRemoteSchemaReducer.js
@@ -318,7 +318,6 @@ const modifyRemoteSchema = () => {
return (dispatch, getState) => {
const currState = getState().remoteSchemas.addData;
const remoteSchemaName = currState.name.trim().replace(/ +/g, '');
- // const url = Endpoints.getSchema;
const upQueryArgs = [];
const downQueryArgs = [];
const migrationName = 'update_remote_schema_' + remoteSchemaName;
@@ -345,9 +344,10 @@ const modifyRemoteSchema = () => {
},
};
- resolveObj.definition.headers = [
- ...getReqHeader(getState().remoteSchemas.headerData.headers),
- ];
+ resolveObj.definition.headers = getReqHeader(
+ getState().remoteSchemas.headerData.headers
+ );
+
if (resolveObj.definition.url) {
delete resolveObj.definition.url_from_env;
} else {
diff --git a/console/src/components/Services/RemoteSchema/Edit/Edit.js b/console/src/components/Services/RemoteSchema/Edit/Edit.js
index be554af7fc9..da74a3fe4ff 100644
--- a/console/src/components/Services/RemoteSchema/Edit/Edit.js
+++ b/console/src/components/Services/RemoteSchema/Edit/Edit.js
@@ -22,6 +22,7 @@ import { NotFoundError } from '../../../Error/PageNotFound';
import globals from '../../../../Globals';
import { getConfirmation } from '../../../Common/utils/jsUtils';
+import styles from '../RemoteSchema.scss';
const prefixUrl = globals.urlPrefix + appPrefix;
@@ -49,17 +50,17 @@ class Edit extends React.Component {
]);
}
- UNSAFE_componentWillReceiveProps(nextProps) {
+ componentDidUpdate(prevProps) {
if (
- nextProps.params.remoteSchemaName !== this.props.params.remoteSchemaName
+ prevProps.params.remoteSchemaName !== this.props.params.remoteSchemaName
) {
Promise.all([
this.props.dispatch(
- fetchRemoteSchema(nextProps.params.remoteSchemaName)
+ fetchRemoteSchema(this.props.params.remoteSchemaName)
),
this.props.dispatch({
type: VIEW_REMOTE_SCHEMA,
- data: nextProps.params.remoteSchemaName,
+ data: this.props.params.remoteSchemaName,
}),
]);
}
@@ -120,11 +121,23 @@ class Edit extends React.Component {
throw new NotFoundError();
}
- const styles = require('../RemoteSchema.scss');
-
- const { isFetching, isRequesting, editState } = this.props;
+ const {
+ isFetching,
+ isRequesting,
+ editState,
+ inconsistentObjects,
+ } = this.props;
const { remoteSchemaName } = this.props.params;
+ const inconsistencyDetails = inconsistentObjects.find(
+ inconObj =>
+ inconObj.type === 'remote_schema' &&
+ inconObj?.definition?.name === remoteSchemaName
+ );
+
+ const fixInconsistencyMsg =
+ 'This remote schema is in an inconsistent state. Please fix inconsistencies and reload metadata first';
+
const generateMigrateBtns = () => {
return 'isModify' in editState && !editState.isModify ? (
@@ -137,7 +150,8 @@ class Edit extends React.Component {
this.modifyClick();
}}
data-test={'remote-schema-edit-modify-btn'}
- disabled={isRequesting}
+ disabled={isRequesting || inconsistencyDetails}
+ title={inconsistencyDetails ? fixInconsistencyMsg : ''}
>
Modify
@@ -148,7 +162,8 @@ class Edit extends React.Component {
e.preventDefault();
this.handleDeleteRemoteSchema(e);
}}
- disabled={isRequesting}
+ disabled={isRequesting || inconsistencyDetails}
+ title={inconsistencyDetails ? fixInconsistencyMsg : ''}
data-test={'remote-schema-edit-delete-btn'}
>
{isRequesting ? 'Deleting ...' : 'Delete'}
@@ -254,6 +269,7 @@ const mapStateToProps = state => {
...state.remoteSchemas.headerData,
allRemoteSchemas: state.remoteSchemas.listData.remoteSchemas,
dataHeaders: { ...state.tables.dataHeaders },
+ inconsistentObjects: state.metadata.inconsistentObjects,
};
};
diff --git a/console/src/components/Services/RemoteSchema/Edit/View.js b/console/src/components/Services/RemoteSchema/Edit/View.js
index 05348e372da..9afb3036fc2 100644
--- a/console/src/components/Services/RemoteSchema/Edit/View.js
+++ b/console/src/components/Services/RemoteSchema/Edit/View.js
@@ -1,28 +1,56 @@
import React from 'react';
-
import CommonTabLayout from '../../../Common/Layout/CommonTabLayout/CommonTabLayout';
import tabInfo from './tabInfo';
-import Tooltip from 'react-bootstrap/lib/Tooltip';
-import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger';
import { push } from 'react-router-redux';
-
import {
fetchRemoteSchema,
RESET,
getHeaderEvents,
} from '../Add/addRemoteSchemaReducer';
-
import { VIEW_REMOTE_SCHEMA } from '../Actions';
import ReloadRemoteSchema from '../../Settings/MetadataOptions/ReloadRemoteSchema';
-
import { appPrefix } from '../constants';
-
-import { NotFoundError } from '../../../Error/PageNotFound';
-
import globals from '../../../../Globals';
+import styles from '../RemoteSchema.scss';
+import ToolTip from '../../../Common/Tooltip/Tooltip';
+import WarningSymbol from '../../../Common/WarningSymbol/WarningSymbol';
const prefixUrl = globals.urlPrefix + appPrefix;
+const RSHeadersDisplay = ({ data }) =>
+ data.length > 0 ? (
+
+ Headers
+
+ {data &&
+ data
+ .filter(header => !!header.name)
+ .map((header, index) => [
+
+
+ {`${header.name}: `}
+ {header.type === 'static'
+ ? header.value
+ : '<' + header.value + '>'}
+
+ ,
+ index !== data.length - 1 ?
: null,
+ ])}
+
+
+ ) : null;
+
+const RSReloadSchema = ({ readOnlyMode, remoteSchemaName, ...props }) =>
+ !readOnlyMode && remoteSchemaName && remoteSchemaName.length > 0 ? (
+
+
+
+
+ ) : null;
+
class ViewStitchedSchema extends React.Component {
componentDidMount() {
const { remoteSchemaName } = this.props.params;
@@ -35,17 +63,17 @@ class ViewStitchedSchema extends React.Component {
]);
}
- UNSAFE_componentWillReceiveProps(nextProps) {
+ componentDidUpdate(prevProps) {
if (
- nextProps.params.remoteSchemaName !== this.props.params.remoteSchemaName
+ prevProps.params.remoteSchemaName !== this.props.params.remoteSchemaName
) {
Promise.all([
this.props.dispatch(
- fetchRemoteSchema(nextProps.params.remoteSchemaName)
+ fetchRemoteSchema(this.props.params.remoteSchemaName)
),
this.props.dispatch({
type: VIEW_REMOTE_SCHEMA,
- data: nextProps.params.remoteSchemaName,
+ data: this.props.params.remoteSchemaName,
}),
]);
}
@@ -69,19 +97,14 @@ class ViewStitchedSchema extends React.Component {
}
render() {
- const currentRemoteSchema = this.props.allRemoteSchemas.find(
- r => r.name === this.props.params.remoteSchemaName
- );
-
- if (!currentRemoteSchema) {
- // throw a 404 exception
- throw new NotFoundError();
- }
-
- const styles = require('../RemoteSchema.scss');
-
const { remoteSchemaName } = this.props.params;
- const { manualUrl, envName, headers, readOnlyMode } = this.props;
+ const {
+ manualUrl,
+ envName,
+ headers,
+ readOnlyMode,
+ inconsistentObjects,
+ } = this.props;
const filterHeaders = headers.filter(h => !!h.name);
@@ -92,21 +115,14 @@ class ViewStitchedSchema extends React.Component {
},
{
title: 'Manage',
- url: appPrefix + '/' + 'manage',
+ url: `${appPrefix}/manage`,
},
];
if (remoteSchemaName) {
breadCrumbs.push({
title: remoteSchemaName.trim(),
- url:
- appPrefix +
- '/' +
- 'manage' +
- '/' +
- remoteSchemaName.trim() +
- '/' +
- 'details',
+ url: `${appPrefix}/manage/${remoteSchemaName.trim()}/details`,
});
breadCrumbs.push({
title: 'details',
@@ -114,33 +130,18 @@ class ViewStitchedSchema extends React.Component {
});
}
- const refresh = (
-
- If your remote schema has changed, you need to refresh the GraphQL
- Engine metadata to query the modified schema
-
- );
+ let tabInfoCopy = tabInfo;
if (readOnlyMode) {
- delete tabInfo.modify;
+ const { modify, ...rest } = tabInfoCopy;
+ tabInfoCopy = rest;
}
- const showReloadRemoteSchema =
- !readOnlyMode && remoteSchemaName && remoteSchemaName.length > 0 ? (
-
-
-
-
-
-
-
-
-
-
- ) : null;
+ const inconsistencyDetails = inconsistentObjects.find(
+ inconObj =>
+ inconObj.type === 'remote_schema' &&
+ inconObj?.definition?.name === remoteSchemaName
+ );
return (
@@ -164,37 +165,35 @@ class ViewStitchedSchema extends React.Component {
GraphQL Server URL
{manualUrl || `<${envName}>`}
- {filterHeaders.length > 0 ? (
-
- Headers
-
- {filterHeaders &&
- filterHeaders
- .filter(k => !!k.name)
- .map((h, i) => [
-
-
- {h.name} :{' '}
- {h.type === 'static'
- ? h.value
- : '<' + h.value + '>'}
-
- ,
- i !== filterHeaders.length - 1 ?
: null,
- ])}
-
-
- ) : null}
- {/*
-
- Webhook
- in-use/bypassed
-
- */}
+
- {showReloadRemoteSchema}
+ {inconsistencyDetails && (
+
+
+
+
+ This remote schema is in an inconsistent state.
+
+
+
+ Reason: {inconsistencyDetails.reason}
+
+
+
+ (Please resolve the inconsistencies and reload the remote
+ schema. Fields from this remote schema are currently not
+ exposed over the GraphQL API)
+
+
+
+ )}
+
@@ -210,6 +209,7 @@ const mapStateToProps = state => {
allRemoteSchemas: state.remoteSchemas.listData.remoteSchemas,
dataHeaders: { ...state.tables.dataHeaders },
readOnlyMode: state.main.readOnlyMode,
+ inconsistentObjects: state.metadata.inconsistentObjects,
};
};
diff --git a/console/src/components/Services/RemoteSchema/RemoteSchema.scss b/console/src/components/Services/RemoteSchema/RemoteSchema.scss
index aa815bcd459..636919506fd 100644
--- a/console/src/components/Services/RemoteSchema/RemoteSchema.scss
+++ b/console/src/components/Services/RemoteSchema/RemoteSchema.scss
@@ -1,4 +1,4 @@
-@import "../../Common/Common.scss";
+@import '../../Common/Common.scss';
.addPaddCommom {
padding: 10px 0;
@@ -42,17 +42,12 @@
width: 100%;
padding: 20px;
text-align: center;
- // height: 200px;
- // border: 1px solid #000;
-
- img {
- }
}
.commonBtn {
text-align: center;
padding: 20px 0;
- padding-bottom: 10px
+ padding-bottom: 10px;
}
.readMore {
@@ -61,7 +56,7 @@
}
}
-.iconWrapper{
+.iconWrapper {
padding: 20px 0;
.icon {
@@ -140,7 +135,7 @@
}
.red_button {
- color: #FFF;
+ color: #fff;
}
a {
@@ -166,7 +161,6 @@
.set_line_height {
line-height: 26px;
}
-
}
.remoteSchemaImg {
@@ -193,7 +187,7 @@
display: flex;
align-items: center;
- a{
+ a {
color: #909090;
}
@@ -260,24 +254,24 @@
display: inline-block;
}
- .instructionsWrapper, .instructionsWrapperPos {
+ .instructionsWrapper,
+ .instructionsWrapperPos {
margin-top: 20px;
- border-top: 1px solid #DEDEDE;
+ border-top: 1px solid #dedede;
.instructions {
padding: 12px 0;
}
}
- .instructionsWrapper
- {
+ .instructionsWrapper {
position: relative;
}
- .instructionsWrapperPos
- {
+ .instructionsWrapperPos {
position: static;
}
- .instructionsWrapper:hover, .instructionsWrapperPos:hover {
+ .instructionsWrapper:hover,
+ .instructionsWrapperPos:hover {
.instructions {
- color: #505050
+ color: #505050;
}
.rightArrow {
diff --git a/console/src/components/Services/RemoteSchema/RemoteSchemaPageContainer.js b/console/src/components/Services/RemoteSchema/RemoteSchemaPageContainer.js
index 64d2997dab4..e679e99083c 100644
--- a/console/src/components/Services/RemoteSchema/RemoteSchemaPageContainer.js
+++ b/console/src/components/Services/RemoteSchema/RemoteSchemaPageContainer.js
@@ -5,10 +5,10 @@ import PropTypes from 'prop-types';
import LeftContainer from '../../Common/Layout/LeftContainer/LeftContainer';
import PageContainer from '../../Common/Layout/PageContainer/PageContainer';
import RemoteSchemaSubSidebar from './RemoteSchemaSubSidebar';
+import styles from '../../Common/TableCommon/Table.scss';
class RemoteSchemaPageContainer extends React.Component {
render() {
- const styles = require('../../Common/TableCommon/Table.scss');
const { appPrefix, children } = this.props;
const currentLocation = location.pathname;
diff --git a/console/src/components/Services/RemoteSchema/RemoteSchemaSubSidebar.js b/console/src/components/Services/RemoteSchema/RemoteSchemaSubSidebar.js
index cd86a5c7cd6..b76605f5288 100644
--- a/console/src/components/Services/RemoteSchema/RemoteSchemaSubSidebar.js
+++ b/console/src/components/Services/RemoteSchema/RemoteSchemaSubSidebar.js
@@ -2,6 +2,8 @@ import React from 'react';
import { Link } from 'react-router';
import LeftSubSidebar from '../../Common/Layout/LeftSubSidebar/LeftSubSidebar';
+import styles from '../../Common/Layout/LeftSubSidebar/LeftSubSidebar.scss';
+import WarningSymbol from '../../Common/WarningSymbol/WarningSymbol';
const RemoteSchemaSubSidebar = ({
appPrefix,
@@ -12,8 +14,12 @@ const RemoteSchemaSubSidebar = ({
filterItem,
viewRemoteSchema,
main,
+ ...props
}) => {
- const styles = require('../../Common/Layout/LeftSubSidebar/LeftSubSidebar.scss');
+ const { inconsistentObjects } = props.metadata;
+ const inconsistentRemoteSchemas = inconsistentObjects.filter(
+ inconObject => inconObject.type === 'remote_schema'
+ );
function tableSearch(e) {
const searchTerm = e.target.value;
@@ -35,7 +41,7 @@ const RemoteSchemaSubSidebar = ({
const getChildList = () => {
const _dataList = searchQuery ? filtered : dataList;
- let childList;
+ let childList = [];
if (_dataList.length === 0) {
childList = (
);
} else {
- childList = _dataList.map((d, i) => {
- let activeTableClass = '';
- if (
- d.name === viewRemoteSchema &&
- location.pathname.includes(viewRemoteSchema)
- ) {
- activeTableClass = styles.activeLink;
- }
+ if (_dataList.length > 0) {
+ childList = _dataList.map((d, i) => {
+ let activeTableClass = '';
- return (
-
- elem.definition.name === d.name
+ );
+
+ return (
+
-
- {d.name}
-
-
- );
- });
+
+
+ {d.name}
+ {inconsistentCurrentSchema ? (
+
+ ) : null}
+
+
+ );
+ });
+ }
}
return childList;
diff --git a/console/src/components/Services/Settings/Actions.js b/console/src/components/Services/Settings/Actions.js
index 006d3e355c1..7628961a218 100644
--- a/console/src/components/Services/Settings/Actions.js
+++ b/console/src/components/Services/Settings/Actions.js
@@ -208,11 +208,6 @@ const handleInconsistentObjects = inconsistentObjects => {
inconsistentObjects,
'functions'
);
- const filteredRemoteSchemas = filterInconsistentMetadataObjects(
- remoteSchemas,
- inconsistentObjects,
- 'remote_schemas'
- );
const filteredActions = filterInconsistentMetadataObjects(
actions,
inconsistentObjects,
@@ -221,7 +216,7 @@ const handleInconsistentObjects = inconsistentObjects => {
dispatch(setConsistentSchema(filteredSchema));
dispatch(setConsistentFunctions(filteredFunctions));
- dispatch(setConsistentRemoteSchemas(filteredRemoteSchemas));
+ dispatch(setConsistentRemoteSchemas(remoteSchemas));
dispatch(setActions(filteredActions));
}
};
@@ -234,9 +229,7 @@ export const loadInconsistentObjects = (reloadConfig, successCb, failureCb) => {
const { shouldReloadMetadata, shouldReloadRemoteSchemas } = reloadConfig;
const loadQuery = shouldReloadMetadata
- ? getReloadCacheAndGetInconsistentObjectsQuery(
- shouldReloadRemoteSchemas === false ? false : true
- )
+ ? getReloadCacheAndGetInconsistentObjectsQuery(shouldReloadRemoteSchemas)
: inconsistentObjectsQuery;
dispatch({ type: LOADING_METADATA });
diff --git a/console/src/components/Services/Settings/MetadataOptions/ReloadRemoteSchema.js b/console/src/components/Services/Settings/MetadataOptions/ReloadRemoteSchema.js
index 7d2b621ad64..7e72e9c4d89 100644
--- a/console/src/components/Services/Settings/MetadataOptions/ReloadRemoteSchema.js
+++ b/console/src/components/Services/Settings/MetadataOptions/ReloadRemoteSchema.js
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Button from '../../../Common/Button/Button';
import { reloadRemoteSchema } from '../Actions';
+import metaDataStyles from '../Settings.scss';
import {
showSuccessNotification,
@@ -17,7 +18,6 @@ class ReloadRemoteSchema extends Component {
render() {
const { dispatch, remoteSchemaName } = this.props;
const { isReloading } = this.state;
- const metaDataStyles = require('../Settings.scss');
const reloadRemoteMetadataHandler = () => {
this.setState({ isReloading: true });
dispatch(
diff --git a/console/src/components/Services/Settings/MetadataStatus/MetadataStatus.js b/console/src/components/Services/Settings/MetadataStatus/MetadataStatus.js
index d3e455b9080..ddca51e1a3f 100644
--- a/console/src/components/Services/Settings/MetadataStatus/MetadataStatus.js
+++ b/console/src/components/Services/Settings/MetadataStatus/MetadataStatus.js
@@ -133,7 +133,7 @@ const MetadataStatus = ({ dispatch, metadata }) => {
of the metadata
- The console will also not be able to display these inconsistent
+ The console might also not be able to display these inconsistent
objects