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 ? ( -
- - - - - -