mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
change default endpoint to v1/graphql; remove semver checks (#2181)
This commit is contained in:
parent
76ceb707f4
commit
3ef1219fa0
@ -78,6 +78,7 @@
|
||||
"jsx-a11y/anchor-is-valid": 0,
|
||||
"jsx-a11y/lang": 0,
|
||||
"jsx-a11y/alt-text": 0,
|
||||
"jsx-a11y/no-autofocus": 0,
|
||||
"max-len": 0,
|
||||
"no-continue": 0
|
||||
},
|
||||
|
@ -15,7 +15,7 @@
|
||||
"start": "concurrently --kill-others \"npm run start-prod\"",
|
||||
"start-prod": "better-npm-run start-prod",
|
||||
"build": "webpack --progress -p --colors --display-error-details --config webpack/prod.config.js",
|
||||
"server-build": "npm run build && mkdir -p static/dist/versioned && cp static/dist/*.js static/dist/*.css static/dist/versioned/ && gzip -r static/dist/versioned",
|
||||
"server-build": "npm run build && mkdir -p static/dist/versioned && cp static/dist/*.js static/dist/*.css static/dist/versioned/ && gzip -r -f static/dist/versioned",
|
||||
"build-unused": "webpack --verbose --colors --display-error-details --config webpack/prod.config.js --json | webpack-unused -s src",
|
||||
"postinstall": "webpack --display-error-details --config webpack/prod.config.js",
|
||||
"lint": "eslint -c .eslintrc src api",
|
||||
|
@ -8,7 +8,7 @@ const hasuractlUrl = hasuractlApiHost + ':' + hasuractlApiPort;
|
||||
|
||||
const Endpoints = {
|
||||
getSchema: `${baseUrl}/v1/query`,
|
||||
graphQLUrl: `${baseUrl}/v1alpha1/graphql`,
|
||||
graphQLUrl: `${baseUrl}/v1/graphql`,
|
||||
schemaChange: `${baseUrl}/v1/query`,
|
||||
query: `${baseUrl}/v1/query`,
|
||||
rawSQL: `${baseUrl}/v1/query`,
|
||||
|
@ -19,7 +19,7 @@ class ErrorBoundary extends React.Component {
|
||||
this.setState({ hasError: true, info: info, error: error });
|
||||
// TODO logErrorToMyService(error, info);
|
||||
const { dispatch } = this.props;
|
||||
dispatch(loadInconsistentObjects(null, true)).then(() => {
|
||||
dispatch(loadInconsistentObjects(true)).then(() => {
|
||||
if (this.props.metadata.inconsistentObjects.length > 0) {
|
||||
if (!window.location.pathname.includes('/metadata/status')) {
|
||||
this.setState({ hasError: false, info: null, error: null });
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
ADMIN_SECRET_ERROR,
|
||||
UPDATE_DATA_HEADERS,
|
||||
} from '../Services/Data/DataActions';
|
||||
import semverCheck, { componentsSemver } from '../../helpers/semver';
|
||||
import { changeRequestHeader } from '../Services/ApiExplorer/Actions';
|
||||
|
||||
const SET_MIGRATION_STATUS_SUCCESS = 'Main/SET_MIGRATION_STATUS_SUCCESS';
|
||||
@ -30,6 +31,26 @@ const UPDATE_ADMIN_SECRET_INPUT = 'Main/UPDATE_ADMIN_SECRET_INPUT';
|
||||
const LOGIN_IN_PROGRESS = 'Main/LOGIN_IN_PROGRESS';
|
||||
const LOGIN_ERROR = 'Main/LOGIN_ERROR';
|
||||
|
||||
const SET_SEMVER = 'Main/SET_SEMVER';
|
||||
const setSemverBulk = data => ({
|
||||
type: SET_SEMVER,
|
||||
data,
|
||||
});
|
||||
|
||||
const semverInit = () => {
|
||||
return (dispatch, getState) => {
|
||||
const { serverVersion } = getState().main;
|
||||
if (!serverVersion) {
|
||||
return;
|
||||
}
|
||||
const semverObj = {};
|
||||
Object.keys(componentsSemver).forEach(feature => {
|
||||
semverObj[feature] = semverCheck(feature, serverVersion);
|
||||
});
|
||||
return dispatch(setSemverBulk(semverObj));
|
||||
};
|
||||
};
|
||||
|
||||
const loadMigrationStatus = () => dispatch => {
|
||||
const url = Endpoints.hasuractlMigrateSettings;
|
||||
const options = {
|
||||
@ -237,7 +258,6 @@ const mainReducer = (state = defaultState, action) => {
|
||||
...state,
|
||||
serverVersion: null,
|
||||
};
|
||||
|
||||
case SET_LATEST_SERVER_VERSION_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
@ -285,7 +305,11 @@ const mainReducer = (state = defaultState, action) => {
|
||||
return { ...state, loginInProgress: action.data };
|
||||
case LOGIN_ERROR:
|
||||
return { ...state, loginError: action.data };
|
||||
|
||||
case SET_SEMVER:
|
||||
return {
|
||||
...state,
|
||||
semver: { ...action.data },
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@ -305,4 +329,5 @@ export {
|
||||
validateLogin,
|
||||
loadServerVersion,
|
||||
checkServerUpdates,
|
||||
semverInit,
|
||||
};
|
||||
|
@ -6,10 +6,9 @@ import globals from '../../Globals';
|
||||
import * as tooltip from './Tooltips';
|
||||
import 'react-toggle/style.css';
|
||||
import Spinner from '../Common/Spinner/Spinner';
|
||||
import { loadServerVersion, checkServerUpdates } from './Actions';
|
||||
import { loadServerVersion, checkServerUpdates, semverInit } from './Actions';
|
||||
import { loadConsoleOpts } from '../../telemetry/Actions.js';
|
||||
import './NotificationOverrides.css';
|
||||
import semverCheck from '../../helpers/semver';
|
||||
import {
|
||||
loadInconsistentObjects,
|
||||
redirectToMetadataStatus,
|
||||
@ -27,23 +26,28 @@ class Main extends React.Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
showBannerNotification: false,
|
||||
showEvents: false,
|
||||
showSchemaStitch: false,
|
||||
};
|
||||
|
||||
this.state.loveConsentState = getLoveConsentState();
|
||||
this.handleBodyClick = this.handleBodyClick.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
document
|
||||
.querySelector('body')
|
||||
.addEventListener('click', this.handleBodyClick);
|
||||
|
||||
dispatch(loadServerVersion()).then(() => {
|
||||
dispatch(loadInconsistentObjects(this.props.serverVersion)).then(() => {
|
||||
dispatch(semverInit());
|
||||
|
||||
dispatch(loadInconsistentObjects()).then(() => {
|
||||
this.handleMetadataRedirect();
|
||||
});
|
||||
|
||||
dispatch(loadConsoleOpts());
|
||||
|
||||
dispatch(checkServerUpdates()).then(() => {
|
||||
let isUpdateAvailable = false;
|
||||
try {
|
||||
@ -66,29 +70,9 @@ class Main extends React.Component {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
this.checkEventsTab().then(() => {
|
||||
this.checkSchemaStitch();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
checkSchemaStitch() {
|
||||
const showSchemaStitch = semverCheck(
|
||||
'schemaStitching',
|
||||
this.props.serverVersion
|
||||
);
|
||||
if (showSchemaStitch) {
|
||||
this.setState({ showSchemaStitch: true });
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
checkEventsTab() {
|
||||
const showEvents = semverCheck('eventsTab', this.props.serverVersion);
|
||||
if (showEvents) {
|
||||
this.setState({ showEvents: true });
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
handleBodyClick(e) {
|
||||
const heartDropDownOpen = document.querySelectorAll(
|
||||
'#dropdown_wrapper.open'
|
||||
@ -100,14 +84,17 @@ class Main extends React.Component {
|
||||
document.getElementById('dropdown_wrapper').classList.remove('open');
|
||||
}
|
||||
}
|
||||
|
||||
handleDropdownToggle() {
|
||||
document.getElementById('dropdown_wrapper').classList.toggle('open');
|
||||
}
|
||||
|
||||
handleMetadataRedirect() {
|
||||
if (this.props.metadata.inconsistentObjects.length > 0) {
|
||||
this.props.dispatch(redirectToMetadataStatus());
|
||||
}
|
||||
}
|
||||
|
||||
closeLoveIcon() {
|
||||
const s = {
|
||||
isDismissed: true,
|
||||
@ -117,6 +104,7 @@ class Main extends React.Component {
|
||||
loveConsentState: { ...getLoveConsentState() },
|
||||
});
|
||||
}
|
||||
|
||||
closeUpdateBanner() {
|
||||
const { latestServerVersion } = this.props;
|
||||
window.localStorage.setItem(
|
||||
@ -399,68 +387,6 @@ class Main extends React.Component {
|
||||
return helpDropdownPosStyle;
|
||||
};
|
||||
|
||||
const getRemoteSchemaLink = () => {
|
||||
let remoteSchemaLink = null;
|
||||
|
||||
if (this.state.showSchemaStitch) {
|
||||
remoteSchemaLink = (
|
||||
<OverlayTrigger placement="right" overlay={tooltip.customresolver}>
|
||||
<li>
|
||||
<Link
|
||||
className={
|
||||
currentActiveBlock === 'remote-schemas'
|
||||
? styles.navSideBarActive
|
||||
: ''
|
||||
}
|
||||
to={appPrefix + '/remote-schemas/manage/schemas'}
|
||||
>
|
||||
<div className={styles.iconCenter}>
|
||||
<i
|
||||
title="Remote Schemas"
|
||||
className="fa fa-plug"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<p>Remote Schemas</p>
|
||||
</Link>
|
||||
</li>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
return remoteSchemaLink;
|
||||
};
|
||||
|
||||
const getEventsLink = () => {
|
||||
let eventsLink = null;
|
||||
|
||||
if (this.state.showEvents) {
|
||||
eventsLink = (
|
||||
<OverlayTrigger placement="right" overlay={tooltip.events}>
|
||||
<li>
|
||||
<Link
|
||||
className={
|
||||
currentActiveBlock === 'events' ? styles.navSideBarActive : ''
|
||||
}
|
||||
to={appPrefix + '/events/manage/triggers'}
|
||||
>
|
||||
<div className={styles.iconCenter}>
|
||||
<i
|
||||
title="Events"
|
||||
className="fa fa-cloud"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<p>Events</p>
|
||||
</Link>
|
||||
</li>
|
||||
</OverlayTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
return eventsLink;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.flexRow}>
|
||||
@ -525,10 +451,51 @@ class Main extends React.Component {
|
||||
</Link>
|
||||
</li>
|
||||
</OverlayTrigger>
|
||||
|
||||
{getRemoteSchemaLink()}
|
||||
|
||||
{getEventsLink()}
|
||||
<OverlayTrigger
|
||||
placement="right"
|
||||
overlay={tooltip.customresolver}
|
||||
>
|
||||
<li>
|
||||
<Link
|
||||
className={
|
||||
currentActiveBlock === 'remote-schemas'
|
||||
? styles.navSideBarActive
|
||||
: ''
|
||||
}
|
||||
to={appPrefix + '/remote-schemas/manage/schemas'}
|
||||
>
|
||||
<div className={styles.iconCenter}>
|
||||
<i
|
||||
title="Remote Schemas"
|
||||
className="fa fa-plug"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<p>Remote Schemas</p>
|
||||
</Link>
|
||||
</li>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger placement="right" overlay={tooltip.events}>
|
||||
<li>
|
||||
<Link
|
||||
className={
|
||||
currentActiveBlock === 'events'
|
||||
? styles.navSideBarActive
|
||||
: ''
|
||||
}
|
||||
to={appPrefix + '/events/manage/triggers'}
|
||||
>
|
||||
<div className={styles.iconCenter}>
|
||||
<i
|
||||
title="Events"
|
||||
className="fa fa-cloud"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<p>Events</p>
|
||||
</Link>
|
||||
</li>
|
||||
</OverlayTrigger>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="dropdown_wrapper" className={styles.clusterInfoWrapper}>
|
||||
|
@ -144,21 +144,17 @@ const graphQLFetcherFinal = (graphQLParams, url, headers) => {
|
||||
};
|
||||
|
||||
/* Analyse Fetcher */
|
||||
const analyzeFetcher = (url, headers, analyzeApiChange) => {
|
||||
const analyzeFetcher = (url, headers) => {
|
||||
return query => {
|
||||
const editedQuery = {
|
||||
query,
|
||||
};
|
||||
let user = {};
|
||||
|
||||
const user = {
|
||||
'x-hasura-role': 'admin',
|
||||
};
|
||||
|
||||
const reqHeaders = getHeadersAsJSON(headers);
|
||||
if (!analyzeApiChange) {
|
||||
user.role = 'admin';
|
||||
user.headers = reqHeaders;
|
||||
} else {
|
||||
user = {
|
||||
'x-hasura-role': 'admin',
|
||||
};
|
||||
}
|
||||
|
||||
// Check if x-hasura-role is available in some form in the headers
|
||||
const totalHeaders = Object.keys(reqHeaders);
|
||||
@ -176,6 +172,7 @@ const analyzeFetcher = (url, headers, analyzeApiChange) => {
|
||||
});
|
||||
|
||||
editedQuery.user = user;
|
||||
|
||||
return fetch(`${url}/explain`, {
|
||||
method: 'post',
|
||||
headers: reqHeaders,
|
||||
|
@ -6,7 +6,6 @@ import OneGraphExplorer from '../OneGraphExplorer/OneGraphExplorer';
|
||||
|
||||
import { clearCodeMirrorHints, setQueryVariableSectionHeight } from './utils';
|
||||
import { analyzeFetcher, graphQLFetcherFinal } from '../Actions';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
import './GraphiQL.css';
|
||||
|
||||
@ -18,29 +17,13 @@ class GraphiQLWrapper extends Component {
|
||||
error: false,
|
||||
noSchema: false,
|
||||
onBoardingEnabled: false,
|
||||
supportAnalyze: false,
|
||||
analyzeApiChange: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.data.serverVersion) {
|
||||
this.checkSemVer(this.props.data.serverVersion).then(() =>
|
||||
this.checkNewAnalyzeVersion(this.props.data.serverVersion)
|
||||
);
|
||||
}
|
||||
|
||||
setQueryVariableSectionHeight();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.data.serverVersion !== this.props.data.serverVersion) {
|
||||
this.checkSemVer(nextProps.data.serverVersion).then(() =>
|
||||
this.checkNewAnalyzeVersion(nextProps.data.serverVersion)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearCodeMirrorHints();
|
||||
}
|
||||
@ -49,52 +32,10 @@ class GraphiQLWrapper extends Component {
|
||||
return !nextProps.headerFocus;
|
||||
}
|
||||
|
||||
checkSemVer(version) {
|
||||
try {
|
||||
const showAnalyze = semverCheck('sqlAnalyze', version);
|
||||
if (showAnalyze) {
|
||||
this.updateAnalyzeState(true);
|
||||
} else {
|
||||
this.updateAnalyzeState(false);
|
||||
}
|
||||
} catch (e) {
|
||||
this.updateAnalyzeState(false);
|
||||
console.error(e);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
checkNewAnalyzeVersion(version) {
|
||||
try {
|
||||
const analyzeApiChange = semverCheck('analyzeApiChange', version);
|
||||
if (analyzeApiChange) {
|
||||
this.updateAnalyzeApiState(true);
|
||||
} else {
|
||||
this.updateAnalyzeApiState(false);
|
||||
}
|
||||
} catch (e) {
|
||||
this.updateAnalyzeApiState(false);
|
||||
console.error(e);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateAnalyzeState(supportAnalyze) {
|
||||
this.setState({
|
||||
supportAnalyze: supportAnalyze,
|
||||
});
|
||||
}
|
||||
|
||||
updateAnalyzeApiState(analyzeApiChange) {
|
||||
this.setState({
|
||||
analyzeApiChange: analyzeApiChange,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const styles = require('../../../Common/Common.scss');
|
||||
|
||||
const { supportAnalyze, analyzeApiChange, headerFocus } = this.state;
|
||||
const { headerFocus } = this.state;
|
||||
|
||||
const { numberOfTables, urlParams } = this.props;
|
||||
const graphqlNetworkData = this.props.data;
|
||||
@ -113,16 +54,15 @@ class GraphiQLWrapper extends Component {
|
||||
|
||||
const analyzeFetcherInstance = analyzeFetcher(
|
||||
graphqlNetworkData.url,
|
||||
graphqlNetworkData.headers,
|
||||
analyzeApiChange
|
||||
graphqlNetworkData.headers
|
||||
);
|
||||
|
||||
const renderGraphiql = graphiqlProps => {
|
||||
return (
|
||||
<GraphiQL
|
||||
fetcher={graphQLFetcher}
|
||||
supportAnalyze
|
||||
analyzeFetcher={analyzeFetcherInstance}
|
||||
supportAnalyze={supportAnalyze}
|
||||
{...graphiqlProps}
|
||||
/>
|
||||
);
|
||||
|
@ -32,7 +32,7 @@ dataApisContent.push({
|
||||
},
|
||||
request: {
|
||||
method: 'POST',
|
||||
url: getUrl('/v1alpha1/graphql'),
|
||||
url: getUrl('/v1/graphql'),
|
||||
headers: defaultHeader,
|
||||
bodyType: 'graphql',
|
||||
params: JSON.stringify({}, null, 4),
|
||||
|
@ -44,7 +44,7 @@ class Common extends React.Component {
|
||||
|
||||
const graphqlurl = (
|
||||
<Tooltip id="tooltip-cascade">
|
||||
Remote GraphQL server’s URL. E.g. https://my-domain/v1alpha1/graphql
|
||||
Remote GraphQL server’s URL. E.g. https://my-domain/v1/graphql
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
|
@ -362,7 +362,7 @@ const loadSchema = () => (dispatch, getState) => {
|
||||
);
|
||||
}
|
||||
dispatch({ type: LOAD_SCHEMA, allSchemas: schemas });
|
||||
dispatch(loadInconsistentObjects(null, false));
|
||||
dispatch(loadInconsistentObjects(false));
|
||||
},
|
||||
error => {
|
||||
console.error('Failed to load schema ' + JSON.stringify(error));
|
||||
|
@ -6,7 +6,6 @@ import { Link } from 'react-router';
|
||||
import LeftSubSidebar from '../../Common/Layout/LeftSubSidebar/LeftSubSidebar';
|
||||
|
||||
import { LISTING_SCHEMA, UPDATE_TRACKED_FUNCTIONS } from './DataActions';
|
||||
import semverCheck from '../../../helpers/semver';
|
||||
|
||||
const appPrefix = '/data';
|
||||
|
||||
@ -22,15 +21,12 @@ const DataSubSidebar = ({
|
||||
dispatch,
|
||||
location,
|
||||
currentFunction,
|
||||
serverVersion,
|
||||
metadata,
|
||||
}) => {
|
||||
const styles = require('../../Common/Layout/LeftSubSidebar/LeftSubSidebar.scss');
|
||||
const functionSymbol = require('../../Common/Layout/LeftSubSidebar/function.svg');
|
||||
const functionSymbolActive = require('../../Common/Layout/LeftSubSidebar/function_high.svg');
|
||||
|
||||
const handleFunc = semverCheck('customFunctionSection', serverVersion);
|
||||
|
||||
if (metadata.ongoingRequest) {
|
||||
return null;
|
||||
}
|
||||
@ -60,7 +56,7 @@ const DataSubSidebar = ({
|
||||
type="text"
|
||||
onChange={tableSearch.bind(this)}
|
||||
className="form-control"
|
||||
placeholder={`search table/view${handleFunc ? '/function' : ''}`}
|
||||
placeholder="search table/view/function"
|
||||
data-test="search-tables"
|
||||
/>
|
||||
);
|
||||
|
@ -18,8 +18,6 @@ import { parseCreateSQL } from './utils';
|
||||
import dataHeaders from '../Common/Headers';
|
||||
import returnMigrateUrl from '../Common/getMigrateUrl';
|
||||
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
const MAKING_REQUEST = 'RawSQL/MAKING_REQUEST';
|
||||
const SET_SQL = 'RawSQL/SET_SQL';
|
||||
const SET_CASCADE_CHECKED = 'RawSQL/SET_CASCADE_CHECKED';
|
||||
@ -39,13 +37,8 @@ const executeSQL = (isMigration, migrationName) => (dispatch, getState) => {
|
||||
dispatch(showSuccessNotification('Executing the Query...'));
|
||||
|
||||
const sql = getState().rawSQL.sql;
|
||||
const serverVersion = getState().main.serverVersion;
|
||||
const currMigrationMode = getState().main.migrationMode;
|
||||
|
||||
const handleFunc = semverCheck('customFunctionSection', serverVersion)
|
||||
? true
|
||||
: false;
|
||||
|
||||
const migrateUrl = returnMigrateUrl(currMigrationMode);
|
||||
const isCascadeChecked = getState().rawSQL.isCascadeChecked;
|
||||
|
||||
@ -59,7 +52,7 @@ const executeSQL = (isMigration, migrationName) => (dispatch, getState) => {
|
||||
// check if track view enabled
|
||||
|
||||
if (getState().rawSQL.isTableTrackChecked) {
|
||||
const objects = parseCreateSQL(sql, handleFunc);
|
||||
const objects = parseCreateSQL(sql);
|
||||
|
||||
objects.forEach(object => {
|
||||
const trackQuery = {
|
||||
|
@ -19,7 +19,6 @@ import {
|
||||
} from './Actions';
|
||||
import { modalOpen, modalClose } from './Actions';
|
||||
import globals from '../../../../Globals';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
import './AceEditorFix.css';
|
||||
|
||||
const RawSQL = ({
|
||||
@ -36,7 +35,6 @@ const RawSQL = ({
|
||||
isMigrationChecked,
|
||||
isTableTrackChecked,
|
||||
migrationMode,
|
||||
serverVersion,
|
||||
allSchemas,
|
||||
}) => {
|
||||
const styles = require('../../../Common/TableCommon/Table.scss');
|
||||
@ -58,12 +56,10 @@ const RawSQL = ({
|
||||
'run_sql_migration'
|
||||
</Tooltip>
|
||||
);
|
||||
const trackTableTip = _hasFunctionSupport => (
|
||||
const trackTableTip = () => (
|
||||
<Tooltip id="tooltip-tracktable">
|
||||
{`If you are creating a table/view${
|
||||
_hasFunctionSupport ? '/function' : ''
|
||||
}, checking this will also expose them
|
||||
over the GraphQL API`}
|
||||
If you are creating a table/view/function, checking this will also expose
|
||||
them over the GraphQL API
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@ -135,11 +131,6 @@ const RawSQL = ({
|
||||
);
|
||||
}
|
||||
|
||||
const hasFunctionSupport = semverCheck(
|
||||
'customFunctionSection',
|
||||
serverVersion
|
||||
);
|
||||
|
||||
const getMigrationModal = () => {
|
||||
const onModalClose = () => {
|
||||
dispatch(modalClose());
|
||||
@ -321,9 +312,9 @@ const RawSQL = ({
|
||||
statement fails, none of the statements will be applied.
|
||||
</li>
|
||||
<li>
|
||||
If you are creating a Table/View
|
||||
{hasFunctionSupport ? '/Function' : ''} using Raw SQL, checking the{' '}
|
||||
<b>Track this</b> checkbox will also expose it over the GraphQL API.
|
||||
If you are creating a Table/View/Function using Raw SQL, checking
|
||||
the <b>Track this</b> checkbox will also expose it over the GraphQL
|
||||
API.
|
||||
</li>
|
||||
<li>
|
||||
If migrations are enabled, down migrations will not be generated for
|
||||
@ -381,10 +372,7 @@ const RawSQL = ({
|
||||
/>
|
||||
Track this
|
||||
</label>
|
||||
<OverlayTrigger
|
||||
placement="right"
|
||||
overlay={trackTableTip(hasFunctionSupport)}
|
||||
>
|
||||
<OverlayTrigger placement="right" overlay={trackTableTip()}>
|
||||
<i
|
||||
className={`${styles.add_mar_left_small} fa fa-info-circle`}
|
||||
aria-hidden="true"
|
||||
|
@ -13,10 +13,10 @@ const getSQLValue = value => {
|
||||
return sqlValue.replace(/['"]+/g, '');
|
||||
};
|
||||
|
||||
const parseCreateSQL = (sql, allowFunction) => {
|
||||
const parseCreateSQL = (sql) => {
|
||||
const _objects = [];
|
||||
|
||||
const regExp = allowFunction ? createSQLRegex : createSQLRegexNoFunction;
|
||||
const regExp = createSQLRegex;
|
||||
|
||||
const matches = sql.match(new RegExp(regExp, 'gmi'));
|
||||
if (matches) {
|
||||
|
@ -12,7 +12,6 @@ const ViewHeader = ({
|
||||
currentSchema,
|
||||
migrationMode,
|
||||
dispatch,
|
||||
allowRename,
|
||||
}) => {
|
||||
const styles = require('../../../Common/TableCommon/Table.scss');
|
||||
let capitalised = tabName;
|
||||
@ -65,7 +64,7 @@ const ViewHeader = ({
|
||||
currentValue={tableName}
|
||||
save={saveViewNameChange}
|
||||
loading={false}
|
||||
editable={tabName === 'modify' && allowRename}
|
||||
editable={tabName === 'modify'}
|
||||
dispatch={dispatch}
|
||||
property="view"
|
||||
/>
|
||||
|
@ -14,8 +14,6 @@ import ViewHeader from './ViewHeader';
|
||||
import ViewRows from './ViewRows';
|
||||
import { replace } from 'react-router-redux';
|
||||
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
const genHeadings = headings => {
|
||||
if (headings.length === 0) {
|
||||
return [];
|
||||
@ -78,39 +76,24 @@ class ViewTable extends Component {
|
||||
this.state = {
|
||||
dispatch: props.dispatch,
|
||||
tableName: props.tableName,
|
||||
supportManualTriggers: false,
|
||||
};
|
||||
|
||||
this.getInitialData(this.props.tableName);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.checkSupportedFeatures(this.props.serverVersion);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.serverVersion !== this.props.serverVersion) {
|
||||
this.checkSupportedFeatures(nextProps.serverVersion);
|
||||
}
|
||||
|
||||
if (nextProps.tableName !== this.props.tableName) {
|
||||
this.getInitialData(nextProps.tableName);
|
||||
}
|
||||
}
|
||||
|
||||
checkSupportedFeatures(version) {
|
||||
if (semverCheck('manualTriggers', version)) {
|
||||
this.setState({ supportManualTriggers: true });
|
||||
}
|
||||
}
|
||||
|
||||
getInitialData(tableName) {
|
||||
const { dispatch } = this.props;
|
||||
Promise.all([
|
||||
dispatch(setTable(tableName)),
|
||||
dispatch(vSetDefaults(tableName)),
|
||||
dispatch(vMakeRequest()),
|
||||
this.retrieveManualTriggers(tableName),
|
||||
dispatch(fetchManualTriggers(tableName)),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -127,11 +110,7 @@ class ViewTable extends Component {
|
||||
document.body.offsetHeight - document.body.scrollTop;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.state.supportManualTriggers !== prevState.supportManualTriggers) {
|
||||
this.retrieveManualTriggers(this.state.tableName);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.shouldScrollBottom) {
|
||||
document.body.scrollTop = document.body.offsetHeight - window.innerHeight;
|
||||
}
|
||||
@ -159,13 +138,6 @@ class ViewTable extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
retrieveManualTriggers = tableName => {
|
||||
const { dispatch } = this.props;
|
||||
return this.state.supportManualTriggers
|
||||
? dispatch(fetchManualTriggers(tableName))
|
||||
: Promise.resolve();
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
tableName,
|
||||
|
@ -13,7 +13,6 @@ const TableHeader = ({
|
||||
migrationMode,
|
||||
currentSchema,
|
||||
dispatch,
|
||||
allowRename,
|
||||
}) => {
|
||||
const styles = require('../../../Common/TableCommon/Table.scss');
|
||||
let capitalised = tabName;
|
||||
@ -74,7 +73,7 @@ const TableHeader = ({
|
||||
currentValue={tableName}
|
||||
save={saveTableNameChange}
|
||||
loading={false}
|
||||
editable={tabName === 'modify' && allowRename}
|
||||
editable={tabName === 'modify'}
|
||||
dispatch={dispatch}
|
||||
property="table"
|
||||
/>
|
||||
|
@ -249,8 +249,7 @@ const modifyReducer = (tableName, schemas, modifyStateOrig, action) => {
|
||||
const permState = getBasePermissionsState(
|
||||
action.tableSchema,
|
||||
action.role,
|
||||
action.query,
|
||||
action.insertPermColumnRestriction
|
||||
action.query
|
||||
);
|
||||
return {
|
||||
...modifyState,
|
||||
|
@ -19,7 +19,6 @@ const ColumnEditor = ({
|
||||
onSubmit,
|
||||
dispatch,
|
||||
columnComment,
|
||||
allowRename,
|
||||
columnProperties,
|
||||
selectedProperties,
|
||||
editColumn,
|
||||
@ -138,20 +137,18 @@ const ColumnEditor = ({
|
||||
return (
|
||||
<div className={`${styles.colEditor} container-fluid`}>
|
||||
<form className="form-horizontal" onSubmit={onSubmit}>
|
||||
{allowRename && (
|
||||
<div className={`${styles.display_flex} form-group`}>
|
||||
<label className="col-xs-2">Name</label>
|
||||
<div className="col-xs-6">
|
||||
<input
|
||||
className="input-sm form-control"
|
||||
value={selectedProperties[colName].name}
|
||||
onChange={updateColumnName}
|
||||
type="text"
|
||||
data-test="edit-col-name"
|
||||
/>
|
||||
</div>
|
||||
<div className={`${styles.display_flex} form-group`}>
|
||||
<label className="col-xs-2">Name</label>
|
||||
<div className="col-xs-6">
|
||||
<input
|
||||
className="input-sm form-control"
|
||||
value={selectedProperties[colName].name}
|
||||
onChange={updateColumnName}
|
||||
type="text"
|
||||
data-test="edit-col-name"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={`${styles.display_flex} form-group`}>
|
||||
<label className="col-xs-2">Type</label>
|
||||
<div className="col-xs-6">
|
||||
|
@ -17,7 +17,6 @@ import styles from './ModifyTable.scss';
|
||||
const ColumnEditorList = ({
|
||||
tableSchema,
|
||||
currentSchema,
|
||||
allowRename,
|
||||
columnEdit,
|
||||
dispatch,
|
||||
columnComments,
|
||||
@ -56,7 +55,7 @@ const ColumnEditorList = ({
|
||||
};
|
||||
|
||||
const onSubmit = () => {
|
||||
dispatch(saveColumnChangesSql(colName, col, allowRename));
|
||||
dispatch(saveColumnChangesSql(colName, col));
|
||||
};
|
||||
|
||||
const onDelete = () => {
|
||||
@ -129,7 +128,6 @@ const ColumnEditorList = ({
|
||||
dispatch={dispatch}
|
||||
currentSchema={currentSchema}
|
||||
columnComment={columnComments[col.column_name]}
|
||||
allowRename={allowRename}
|
||||
columnProperties={columnProperties}
|
||||
selectedProperties={columnEdit}
|
||||
editColumn={editColumn}
|
||||
|
@ -162,8 +162,8 @@ const savePrimaryKeys = (tableName, schemaName, constraintName) => {
|
||||
sql: `
|
||||
alter table "${schemaName}"."${tableName}"
|
||||
add constraint "${tableName}_pkey" primary key ( ${selectedPkColumns.join(
|
||||
', '
|
||||
)} );
|
||||
', '
|
||||
)} );
|
||||
`,
|
||||
},
|
||||
});
|
||||
@ -188,8 +188,8 @@ const savePrimaryKeys = (tableName, schemaName, constraintName) => {
|
||||
sql: `
|
||||
alter table "${schemaName}"."${tableName}"
|
||||
add constraint "${constraintName}" primary key ( ${tableSchema.primary_key.columns.join(
|
||||
', '
|
||||
)} );
|
||||
', '
|
||||
)} );
|
||||
`,
|
||||
});
|
||||
}
|
||||
@ -1054,7 +1054,7 @@ const isColumnUnique = (tableSchema, colName) => {
|
||||
);
|
||||
};
|
||||
|
||||
const saveColumnChangesSql = (colName, column, allowRename) => {
|
||||
const saveColumnChangesSql = (colName, column) => {
|
||||
// eslint-disable-line no-unused-vars
|
||||
return (dispatch, getState) => {
|
||||
const columnEdit = getState().tables.modify.columnEdit[colName];
|
||||
@ -1064,7 +1064,7 @@ const saveColumnChangesSql = (colName, column, allowRename) => {
|
||||
const unique = columnEdit.isUnique;
|
||||
const def = columnEdit.default || '';
|
||||
const comment = columnEdit.comment || '';
|
||||
const newName = allowRename ? columnEdit.name : null;
|
||||
const newName = columnEdit.name;
|
||||
const currentSchema = columnEdit.schemaName;
|
||||
// ALTER TABLE <table> ALTER COLUMN <column> TYPE <column_type>;
|
||||
let defWithQuotes;
|
||||
@ -1121,24 +1121,24 @@ const saveColumnChangesSql = (colName, column, allowRename) => {
|
||||
const schemaChangesUp =
|
||||
originalColType !== colType
|
||||
? [
|
||||
{
|
||||
type: 'run_sql',
|
||||
args: {
|
||||
sql: columnChangesUpQuery,
|
||||
},
|
||||
{
|
||||
type: 'run_sql',
|
||||
args: {
|
||||
sql: columnChangesUpQuery,
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
: [];
|
||||
const schemaChangesDown =
|
||||
originalColType !== colType
|
||||
? [
|
||||
{
|
||||
type: 'run_sql',
|
||||
args: {
|
||||
sql: columnChangesDownQuery,
|
||||
},
|
||||
{
|
||||
type: 'run_sql',
|
||||
args: {
|
||||
sql: columnChangesDownQuery,
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
/* column default up/down migration */
|
||||
|
@ -15,45 +15,16 @@ import PrimaryKeyEditor from './PrimaryKeyEditor';
|
||||
import TableCommentEditor from './TableCommentEditor';
|
||||
import ForeignKeyEditor from './ForeignKeyEditor';
|
||||
import UniqueKeyEditor from './UniqueKeyEditor';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
import styles from './ModifyTable.scss';
|
||||
|
||||
class ModifyTable extends React.Component {
|
||||
state = {
|
||||
supportTableColumnRename: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch, serverVersion } = this.props;
|
||||
const { dispatch } = this.props;
|
||||
dispatch({ type: RESET });
|
||||
dispatch(setTable(this.props.tableName));
|
||||
dispatch(fetchTableComment(this.props.tableName));
|
||||
if (serverVersion) {
|
||||
this.checkTableColumnRenameSupport(serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.serverVersion &&
|
||||
nextProps.serverVersion !== this.props.serverVersion
|
||||
) {
|
||||
this.checkTableColumnRenameSupport(nextProps.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
checkTableColumnRenameSupport = serverVersion => {
|
||||
try {
|
||||
if (semverCheck('tableColumnRename', serverVersion)) {
|
||||
this.setState({
|
||||
supportTableColumnRename: true,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
tableName,
|
||||
@ -114,7 +85,6 @@ class ModifyTable extends React.Component {
|
||||
tabName="modify"
|
||||
migrationMode={migrationMode}
|
||||
currentSchema={currentSchema}
|
||||
allowRename={this.state.supportTableColumnRename}
|
||||
/>
|
||||
<br />
|
||||
<div className={`container-fluid ${styles.padd_left_remove}`}>
|
||||
@ -134,7 +104,6 @@ class ModifyTable extends React.Component {
|
||||
<ColumnEditorList
|
||||
tableSchema={tableSchema}
|
||||
columnEdit={columnEdit}
|
||||
allowRename={this.state.supportTableColumnRename}
|
||||
columnComments={columnComments}
|
||||
dispatch={dispatch}
|
||||
currentSchema={currentSchema}
|
||||
|
@ -16,44 +16,16 @@ import {
|
||||
import { ordinalColSort } from '../utils';
|
||||
import { setTable, fetchTableComment } from '../DataActions';
|
||||
import Button from '../../../Common/Button/Button';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
class ModifyView extends Component {
|
||||
state = {
|
||||
supportTableColumnRename: false,
|
||||
};
|
||||
componentDidMount() {
|
||||
const { dispatch, serverVersion } = this.props;
|
||||
const { dispatch } = this.props;
|
||||
dispatch({ type: RESET });
|
||||
dispatch(setTable(this.props.tableName));
|
||||
dispatch(fetchViewDefinition(this.props.tableName, false));
|
||||
dispatch(fetchTableComment(this.props.tableName));
|
||||
if (serverVersion) {
|
||||
this.checkTableColumnRenameSupport(serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.serverVersion &&
|
||||
nextProps.serverVersion !== this.props.serverVersion
|
||||
) {
|
||||
this.checkTableColumnRenameSupport(nextProps.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
checkTableColumnRenameSupport = serverVersion => {
|
||||
try {
|
||||
if (semverCheck('tableColumnRename', serverVersion)) {
|
||||
this.setState({
|
||||
supportTableColumnRename: true,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
modifyViewDefinition = viewName => {
|
||||
// fetch the definition
|
||||
this.props.dispatch(fetchViewDefinition(viewName, true));
|
||||
@ -250,7 +222,6 @@ class ModifyView extends Component {
|
||||
tabName="modify"
|
||||
currentSchema={currentSchema}
|
||||
migrationMode={migrationMode}
|
||||
allowRename={this.state.supportTableColumnRename}
|
||||
/>
|
||||
<br />
|
||||
<div className={'container-fluid ' + styles.padd_left_remove}>
|
||||
|
@ -55,13 +55,11 @@ const permOpenEdit = (
|
||||
tableSchema,
|
||||
role,
|
||||
query,
|
||||
insertPermColumnRestriction
|
||||
) => ({
|
||||
type: PERM_OPEN_EDIT,
|
||||
tableSchema,
|
||||
role,
|
||||
query,
|
||||
insertPermColumnRestriction,
|
||||
});
|
||||
const permSetFilter = filter => ({ type: PERM_SET_FILTER, filter });
|
||||
const permSetFilterSameAs = filter => ({
|
||||
@ -124,7 +122,6 @@ const getBasePermissionsState = (
|
||||
tableSchema,
|
||||
role,
|
||||
query,
|
||||
insertPermColumnRestriction
|
||||
) => {
|
||||
const _permissions = JSON.parse(JSON.stringify(defaultPermissionsState));
|
||||
|
||||
@ -142,12 +139,10 @@ const getBasePermissionsState = (
|
||||
// If the query is insert, transform set object if exists to an array
|
||||
if (q === 'insert' || q === 'update') {
|
||||
// If set is an object
|
||||
if (insertPermColumnRestriction) {
|
||||
if (!_permissions[q].columns) {
|
||||
_permissions[q].columns = tableSchema.columns.map(
|
||||
c => c.column_name
|
||||
);
|
||||
}
|
||||
if (!_permissions[q].columns) {
|
||||
_permissions[q].columns = tableSchema.columns.map(
|
||||
c => c.column_name
|
||||
);
|
||||
}
|
||||
if ('set' in _permissions[q]) {
|
||||
if (
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
permCloseEdit,
|
||||
permSetRoleName,
|
||||
permChangePermissions,
|
||||
permToggleAllowUpsert,
|
||||
// permToggleAllowUpsert,
|
||||
permToggleAllowAggregation,
|
||||
permToggleModifyLimit,
|
||||
permCustomChecked,
|
||||
@ -45,7 +45,6 @@ import EnhancedInput from '../../../Common/InputChecker/InputChecker';
|
||||
import { setTable, fetchViewInfoFromInformationSchema } from '../DataActions';
|
||||
import { getIngForm, getEdForm, escapeRegExp } from '../utils';
|
||||
import { allOperators, getLegacyOperator } from './PermissionBuilder/utils';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
import Button from '../../../Common/Button/Button';
|
||||
import { defaultPresetsState } from '../DataState';
|
||||
|
||||
@ -53,26 +52,22 @@ class Permissions extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {};
|
||||
this.state.viewInfo = {};
|
||||
this.state.showAggregation = false;
|
||||
this.state.showIshowInsertPresets = false;
|
||||
this.state.showUpdatePresets = false;
|
||||
this.state.presetsInfo = {
|
||||
insert: {
|
||||
columnTypeMap: {},
|
||||
},
|
||||
update: {
|
||||
columnTypeMap: {},
|
||||
this.state = {
|
||||
viewInfo: {},
|
||||
presetsInfo: {
|
||||
insert: {
|
||||
columnTypeMap: {},
|
||||
},
|
||||
update: {
|
||||
columnTypeMap: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.serverVersion) {
|
||||
this.checkSemVer(this.props.serverVersion);
|
||||
}
|
||||
this.props.dispatch({ type: RESET });
|
||||
|
||||
const currentSchema = this.props.allSchemas.find(
|
||||
t => t.table_name === this.props.tableName
|
||||
);
|
||||
@ -97,22 +92,6 @@ class Permissions extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.serverVersion !== this.props.serverVersion) {
|
||||
this.checkSemVer(nextProps.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
checkSemVer(version) {
|
||||
this.setState({
|
||||
showAggregation: semverCheck('aggregationPerm', version),
|
||||
showUpsertSection: !semverCheck('permHideUpsertSection', version),
|
||||
showInsertPresets: semverCheck('insertPrefix', version),
|
||||
showUpdatePresets: semverCheck('permUpdatePresets', version),
|
||||
allowInsertPermColumns: semverCheck('insertPermRestrictColumns', version),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
dispatch,
|
||||
@ -315,22 +294,13 @@ class Permissions extends Component {
|
||||
const _permissionsRowsHtml = [];
|
||||
|
||||
const getPermissionsTableRow = (role, newPermRow = null) => {
|
||||
const { allowInsertPermColumns } = this.state;
|
||||
|
||||
const dispatchOpenEdit = queryType => () => {
|
||||
if (newPermRow && permissionsState.newRole !== '') {
|
||||
dispatch(
|
||||
permOpenEdit(tableSchema, permissionsState.newRole, queryType)
|
||||
);
|
||||
} else if (role !== '') {
|
||||
dispatch(
|
||||
permOpenEdit(
|
||||
tableSchema,
|
||||
role,
|
||||
queryType,
|
||||
allowInsertPermColumns
|
||||
)
|
||||
);
|
||||
dispatch(permOpenEdit(tableSchema, role, queryType));
|
||||
} else {
|
||||
document.getElementById('newRoleInput').focus();
|
||||
}
|
||||
@ -583,13 +553,6 @@ class Permissions extends Component {
|
||||
dispatch(permCloseEdit());
|
||||
};
|
||||
|
||||
const {
|
||||
showAggregation,
|
||||
showUpsertSection,
|
||||
showInsertPresets,
|
||||
showUpdatePresets,
|
||||
} = this.state;
|
||||
|
||||
const query = permissionsState.query;
|
||||
|
||||
const noPermissions = !permissionsState[query];
|
||||
@ -930,16 +893,6 @@ class Permissions extends Component {
|
||||
};
|
||||
|
||||
const getColumnSection = () => {
|
||||
const { allowInsertPermColumns } = this.state;
|
||||
|
||||
const getQueriesWithPermColumns = allowInsert => {
|
||||
const queries = ['select', 'update'];
|
||||
if (allowInsert) {
|
||||
queries.push('insert');
|
||||
}
|
||||
return queries;
|
||||
};
|
||||
|
||||
const getColumnList = () => {
|
||||
const _columnList = [];
|
||||
|
||||
@ -1027,9 +980,7 @@ class Permissions extends Component {
|
||||
|
||||
let _columnSection = '';
|
||||
|
||||
const queriesWithPermColumns = getQueriesWithPermColumns(
|
||||
allowInsertPermColumns
|
||||
);
|
||||
const queriesWithPermColumns = ['select', 'update', 'insert'];
|
||||
|
||||
if (queriesWithPermColumns.includes(query)) {
|
||||
const getAccessText = () => {
|
||||
@ -1102,59 +1053,59 @@ class Permissions extends Component {
|
||||
return _columnSection;
|
||||
};
|
||||
|
||||
const getUpsertSection = () => {
|
||||
if (query !== 'insert') {
|
||||
return;
|
||||
}
|
||||
|
||||
const dispatchToggleAllowUpsert = checked => {
|
||||
dispatch(permToggleAllowUpsert(checked));
|
||||
};
|
||||
|
||||
const upsertAllowed = permissionsState.insert
|
||||
? permissionsState.insert.allow_upsert
|
||||
: false;
|
||||
|
||||
const upsertToolTip = (
|
||||
<Tooltip id="tooltip-upsert">
|
||||
Allow upsert queries. Upsert lets you update a row if it already
|
||||
exists, otherwise insert it
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const upsertStatus = upsertAllowed ? 'enabled' : 'disabled';
|
||||
|
||||
return (
|
||||
<CollapsibleToggle
|
||||
title={getSectionHeader(
|
||||
'Upsert queries permissions',
|
||||
upsertToolTip,
|
||||
upsertStatus
|
||||
)}
|
||||
useDefaultTitleStyle
|
||||
testId={'toggle-upsert-permission'}
|
||||
>
|
||||
<div
|
||||
className={sectionClasses}
|
||||
title={noPermissions ? noPermissionsMsg : ''}
|
||||
>
|
||||
<div className="checkbox">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={upsertAllowed}
|
||||
value="toggle_upsert"
|
||||
onChange={e => dispatchToggleAllowUpsert(e.target.checked)}
|
||||
disabled={noPermissions}
|
||||
/>
|
||||
Allow role <b>{permissionsState.role}</b> to make upsert
|
||||
queries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</CollapsibleToggle>
|
||||
);
|
||||
};
|
||||
// const getUpsertSection = () => {
|
||||
// if (query !== 'insert') {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// const dispatchToggleAllowUpsert = checked => {
|
||||
// dispatch(permToggleAllowUpsert(checked));
|
||||
// };
|
||||
//
|
||||
// const upsertAllowed = permissionsState.insert
|
||||
// ? permissionsState.insert.allow_upsert
|
||||
// : false;
|
||||
//
|
||||
// const upsertToolTip = (
|
||||
// <Tooltip id="tooltip-upsert">
|
||||
// Allow upsert queries. Upsert lets you update a row if it already
|
||||
// exists, otherwise insert it
|
||||
// </Tooltip>
|
||||
// );
|
||||
//
|
||||
// const upsertStatus = upsertAllowed ? 'enabled' : 'disabled';
|
||||
//
|
||||
// return (
|
||||
// <CollapsibleToggle
|
||||
// title={getSectionHeader(
|
||||
// 'Upsert queries permissions',
|
||||
// upsertToolTip,
|
||||
// upsertStatus
|
||||
// )}
|
||||
// useDefaultTitleStyle
|
||||
// testId={'toggle-upsert-permission'}
|
||||
// >
|
||||
// <div
|
||||
// className={sectionClasses}
|
||||
// title={noPermissions ? noPermissionsMsg : ''}
|
||||
// >
|
||||
// <div className="checkbox">
|
||||
// <label>
|
||||
// <input
|
||||
// type="checkbox"
|
||||
// checked={upsertAllowed}
|
||||
// value="toggle_upsert"
|
||||
// onChange={e => dispatchToggleAllowUpsert(e.target.checked)}
|
||||
// disabled={noPermissions}
|
||||
// />
|
||||
// Allow role <b>{permissionsState.role}</b> to make upsert
|
||||
// queries
|
||||
// </label>
|
||||
// </div>
|
||||
// </div>
|
||||
// </CollapsibleToggle>
|
||||
// );
|
||||
// };
|
||||
|
||||
const getPresetsSection = action => {
|
||||
if (query !== action) {
|
||||
@ -1802,10 +1753,10 @@ class Permissions extends Component {
|
||||
<div>
|
||||
{getRowSection()}
|
||||
{getColumnSection()}
|
||||
{showAggregation && getAggregationSection()}
|
||||
{showUpsertSection && getUpsertSection()}
|
||||
{showInsertPresets && getPresetsSection('insert')}
|
||||
{showUpdatePresets && getPresetsSection('update')}
|
||||
{getAggregationSection()}
|
||||
{/*{getUpsertSection()}*/}
|
||||
{getPresetsSection('insert')}
|
||||
{getPresetsSection('update')}
|
||||
{getButtonsSection()}
|
||||
{getClonePermsSection()}
|
||||
</div>
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable jsx-a11y/no-autofocus */
|
||||
import React from 'react';
|
||||
import { getRelDef } from './utils';
|
||||
import Button from '../../../Common/Button/Button';
|
||||
@ -60,14 +59,7 @@ class RelationshipEditor extends React.Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
dispatch,
|
||||
tableName,
|
||||
relName,
|
||||
relConfig,
|
||||
isObjRel,
|
||||
allowRename,
|
||||
} = this.props;
|
||||
const { dispatch, tableName, relName, relConfig, isObjRel } = this.props;
|
||||
|
||||
const { text, isEditting } = this.state;
|
||||
const { lcol, rtable, rcol } = relConfig;
|
||||
@ -86,16 +78,12 @@ class RelationshipEditor extends React.Component {
|
||||
const collapsed = () => (
|
||||
<div>
|
||||
<Button
|
||||
color={allowRename ? 'white' : 'red'}
|
||||
size={allowRename ? 'xs' : 'sm'}
|
||||
onClick={allowRename ? this.toggleEditor : onDelete}
|
||||
data-test={
|
||||
allowRename
|
||||
? `relationship-toggle-editor-${relName}`
|
||||
: `relationship-remove-${relName}`
|
||||
}
|
||||
color={'white'}
|
||||
size={'xs'}
|
||||
onClick={this.toggleEditor}
|
||||
data-test={`relationship-toggle-editor-${relName}`}
|
||||
>
|
||||
{allowRename ? 'Edit' : 'Remove'}
|
||||
Edit
|
||||
</Button>
|
||||
|
||||
<b>{relName}</b>
|
||||
|
@ -22,7 +22,6 @@ import Button from '../../../Common/Button/Button';
|
||||
import AddManualRelationship from './AddManualRelationship';
|
||||
import suggestedRelationshipsRaw from './autoRelations';
|
||||
import RelationshipEditor from './RelationshipEditor';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
const addRelationshipCellView = (
|
||||
dispatch,
|
||||
@ -308,39 +307,12 @@ const AddRelationship = ({
|
||||
};
|
||||
|
||||
class Relationships extends Component {
|
||||
state = {
|
||||
supportRename: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch, serverVersion, tableName } = this.props;
|
||||
const { dispatch, tableName } = this.props;
|
||||
dispatch({ type: RESET });
|
||||
dispatch(setTable(tableName));
|
||||
if (serverVersion) {
|
||||
this.checkRenameSupport(serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.serverVersion &&
|
||||
nextProps.serverVersion !== this.props.serverVersion
|
||||
) {
|
||||
this.checkRenameSupport(nextProps.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
checkRenameSupport = serverVersion => {
|
||||
try {
|
||||
if (semverCheck('tableColumnRename', serverVersion)) {
|
||||
this.setState({
|
||||
supportRename: true,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const {
|
||||
tableName,
|
||||
@ -418,7 +390,6 @@ class Relationships extends Component {
|
||||
rel.objRel
|
||||
)}
|
||||
isObjRel
|
||||
allowRename={this.state.supportRename}
|
||||
/>
|
||||
) : (
|
||||
<td />
|
||||
@ -435,7 +406,6 @@ class Relationships extends Component {
|
||||
rel.arrRel
|
||||
)}
|
||||
isObjRel={false}
|
||||
allowRename={this.state.supportRename}
|
||||
/>
|
||||
) : (
|
||||
<td />
|
||||
|
@ -10,14 +10,10 @@ import { setTable, UPDATE_REMOTE_SCHEMA_MANUAL_REL } from '../DataActions';
|
||||
import Button from '../../../Common/Button/Button';
|
||||
import AddManualRelationship from './AddManualRelationship';
|
||||
import RelationshipEditor from './RelationshipEditor';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
class RelationshipsView extends Component {
|
||||
state = {
|
||||
supportRename: false,
|
||||
};
|
||||
componentDidMount() {
|
||||
const { dispatch, serverVersion, currentSchema, tableName } = this.props;
|
||||
const { dispatch, currentSchema, tableName } = this.props;
|
||||
dispatch({ type: RESET });
|
||||
dispatch(setTable(tableName));
|
||||
// Sourcing the current schema into manual relationship
|
||||
@ -25,31 +21,8 @@ class RelationshipsView extends Component {
|
||||
type: UPDATE_REMOTE_SCHEMA_MANUAL_REL,
|
||||
data: currentSchema,
|
||||
});
|
||||
if (serverVersion) {
|
||||
this.checkRenameSupport(serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (
|
||||
nextProps.serverVersion &&
|
||||
nextProps.serverVersion !== this.props.serverVersion
|
||||
) {
|
||||
this.checkRenameSupport(nextProps.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
checkRenameSupport = serverVersion => {
|
||||
try {
|
||||
if (semverCheck('tableColumnRename', serverVersion)) {
|
||||
this.setState({
|
||||
supportRename: true,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const {
|
||||
tableName,
|
||||
@ -127,7 +100,6 @@ class RelationshipsView extends Component {
|
||||
rel.objRel
|
||||
)}
|
||||
isObjRel
|
||||
allowRename={this.state.supportRename}
|
||||
/>
|
||||
) : (
|
||||
<td />
|
||||
@ -144,7 +116,6 @@ class RelationshipsView extends Component {
|
||||
rel.arrRel
|
||||
)}
|
||||
isObjRel={false}
|
||||
allowRename={this.state.supportRename}
|
||||
/>
|
||||
) : (
|
||||
<td />
|
||||
|
@ -201,28 +201,8 @@ const loadTableList = schemaName => {
|
||||
dispatch(fetchTableListBySchema(schemaName, UPDATE_TABLE_LIST));
|
||||
};
|
||||
|
||||
const operationToggleColumn = (
|
||||
column,
|
||||
operation,
|
||||
supportColumnChangeFeature
|
||||
) => {
|
||||
const operationToggleColumn = (column, operation) => {
|
||||
return (dispatch, getState) => {
|
||||
if (supportColumnChangeFeature) {
|
||||
if (operation === 'update') {
|
||||
const currentOperations = getState().addTrigger.operations;
|
||||
const currentCols = currentOperations[operation];
|
||||
// check if column is in currentCols. if not, push
|
||||
const isExists = currentCols.includes(column);
|
||||
let finalCols = currentCols;
|
||||
if (isExists) {
|
||||
finalCols = currentCols.filter(col => col !== column);
|
||||
} else {
|
||||
finalCols.push(column);
|
||||
}
|
||||
dispatch({ type: TOGGLE_COLUMNS, cols: finalCols, op: operation });
|
||||
}
|
||||
return;
|
||||
}
|
||||
const currentOperations = getState().addTrigger.operations;
|
||||
const currentCols = currentOperations[operation];
|
||||
// check if column is in currentCols. if not, push
|
||||
@ -237,18 +217,9 @@ const operationToggleColumn = (
|
||||
};
|
||||
};
|
||||
|
||||
const operationToggleAllColumns = (
|
||||
columns,
|
||||
supportListeningToColumnsUpdate
|
||||
) => {
|
||||
const operationToggleAllColumns = columns => {
|
||||
return dispatch => {
|
||||
if (supportListeningToColumnsUpdate) {
|
||||
dispatch({ type: TOGGLE_ALL_COLUMNS, cols: columns });
|
||||
} else {
|
||||
dispatch({ type: TOGGLE_COLUMNS, cols: columns, op: 'insert' });
|
||||
dispatch({ type: TOGGLE_COLUMNS, cols: columns, op: 'update' });
|
||||
dispatch({ type: TOGGLE_COLUMNS, cols: columns, op: 'delete' });
|
||||
}
|
||||
dispatch({ type: TOGGLE_ALL_COLUMNS, cols: columns });
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -33,40 +33,15 @@ import { createTrigger } from './AddActions';
|
||||
import DropdownButton from '../../../Common/DropdownButton/DropdownButton';
|
||||
import CollapsibleToggle from '../../../Common/CollapsibleToggle/CollapsibleToggle';
|
||||
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
class AddTrigger extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.props.dispatch(loadTableList('public'));
|
||||
|
||||
this.state = {
|
||||
supportColumnChangeFeature: false,
|
||||
supportWebhookEnv: false,
|
||||
supportRetryTimeout: false,
|
||||
supportManualTriggerInvocations: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// set defaults
|
||||
this.props.dispatch(setDefaults());
|
||||
if (this.props.serverVersion) {
|
||||
this.checkSemVer(this.props.serverVersion).then(() => {
|
||||
this.checkWebhookEnvSupport(this.props.serverVersion);
|
||||
this.checkRetryTimeoutSupport(this.props.serverVersion);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.serverVersion !== this.props.serverVersion) {
|
||||
this.checkSemVer(nextProps.serverVersion).then(() => {
|
||||
this.checkWebhookEnvSupport(nextProps.serverVersion);
|
||||
this.checkRetryTimeoutSupport(nextProps.serverVersion);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -74,49 +49,6 @@ class AddTrigger extends Component {
|
||||
this.props.dispatch(setDefaults());
|
||||
}
|
||||
|
||||
checkSemVer(version) {
|
||||
try {
|
||||
const supportColumnChangeFeature = semverCheck(
|
||||
'supportColumnChangeTrigger',
|
||||
version
|
||||
);
|
||||
if (supportColumnChangeFeature) {
|
||||
this.updateSupportColumnChangeFeature(true);
|
||||
} else {
|
||||
this.updateSupportColumnChangeFeature(false);
|
||||
}
|
||||
this.checkManualTriggerInvocationSupport(version);
|
||||
} catch (e) {
|
||||
this.updateSupportColumnChangeFeature(false);
|
||||
console.error(e);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
checkWebhookEnvSupport(version) {
|
||||
const supportWebhookEnv = semverCheck('webhookEnvSupport', version);
|
||||
this.setState({ supportWebhookEnv });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
checkRetryTimeoutSupport(version) {
|
||||
const supportRetryTimeout = semverCheck('triggerRetryTimeout', version);
|
||||
this.setState({ supportRetryTimeout });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
checkManualTriggerInvocationSupport(version) {
|
||||
this.setState({
|
||||
supportManualTriggerInvocations: semverCheck('manualTriggers', version),
|
||||
});
|
||||
}
|
||||
|
||||
updateSupportColumnChangeFeature(val) {
|
||||
this.setState({
|
||||
supportColumnChangeFeature: val,
|
||||
});
|
||||
}
|
||||
|
||||
updateWebhookUrlType(e) {
|
||||
const field = e.target.getAttribute('value');
|
||||
if (field === 'env' || field === 'url') {
|
||||
@ -167,10 +99,7 @@ class AddTrigger extends Component {
|
||||
errorMsg = 'Retry interval is not valid';
|
||||
customMsg = 'Retry interval must be a postiive number';
|
||||
}
|
||||
if (
|
||||
this.state.supportRetryTimeout &&
|
||||
(isNaN(iTimeout) || iTimeout <= 0)
|
||||
) {
|
||||
if (isNaN(iTimeout) || iTimeout <= 0) {
|
||||
isValid = false;
|
||||
errorMsg = 'Timeout is not valid';
|
||||
customMsg = 'Timeout must be a positive number';
|
||||
@ -243,12 +172,6 @@ class AddTrigger extends Component {
|
||||
enableManual,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
supportColumnChangeFeature,
|
||||
supportRetryTimeout,
|
||||
supportManualTriggerInvocations,
|
||||
} = this.state;
|
||||
|
||||
const styles = require('../TableCommon/EventTable.scss');
|
||||
|
||||
let createBtnText = 'Create Event Trigger';
|
||||
@ -283,15 +206,13 @@ class AddTrigger extends Component {
|
||||
columns.push(column);
|
||||
});
|
||||
}
|
||||
dispatch(operationToggleAllColumns(columns, supportColumnChangeFeature));
|
||||
dispatch(operationToggleAllColumns(columns));
|
||||
};
|
||||
|
||||
const getColumnList = type => {
|
||||
const dispatchToggleColumn = e => {
|
||||
const column = e.target.value;
|
||||
dispatch(
|
||||
operationToggleColumn(column, type, supportColumnChangeFeature)
|
||||
);
|
||||
dispatch(operationToggleColumn(column, type));
|
||||
};
|
||||
const tableSchema = tableListBySchema.find(
|
||||
t => t.table_name === tableName
|
||||
@ -332,7 +253,7 @@ class AddTrigger extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
const advancedColumnSection = supportColumnChangeFeature ? (
|
||||
const advancedColumnSection = (
|
||||
<div>
|
||||
<h4 className={styles.subheading_text}>
|
||||
Listen columns for update
|
||||
@ -345,8 +266,7 @@ class AddTrigger extends Component {
|
||||
</h4>
|
||||
{selectedOperations.update ? (
|
||||
<div className={styles.clear_fix + ' ' + styles.listenColumnWrapper}>
|
||||
{' '}
|
||||
{getColumnList('update')}{' '}
|
||||
{getColumnList('update')}
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.clear_fix + ' ' + styles.listenColumnWrapper}>
|
||||
@ -354,65 +274,6 @@ class AddTrigger extends Component {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<h4 className={styles.subheading_text}>
|
||||
Advanced - Operation/Columns
|
||||
<OverlayTrigger
|
||||
placement="right"
|
||||
overlay={tooltip.advancedOperationDescription}
|
||||
>
|
||||
<i className="fa fa-question-circle" aria-hidden="true" />
|
||||
</OverlayTrigger>{' '}
|
||||
</h4>
|
||||
<div>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
onChange={handleOperationSelection}
|
||||
className={styles.display_inline + ' ' + styles.add_mar_right}
|
||||
type="checkbox"
|
||||
value="insert"
|
||||
checked={selectedOperations.insert}
|
||||
/>
|
||||
Insert
|
||||
</label>
|
||||
</div>
|
||||
{getColumnList('insert')}
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
onChange={handleOperationSelection}
|
||||
className={styles.display_inline + ' ' + styles.add_mar_right}
|
||||
type="checkbox"
|
||||
value="update"
|
||||
checked={selectedOperations.update}
|
||||
/>
|
||||
Update
|
||||
</label>
|
||||
</div>
|
||||
{getColumnList('update')}
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<div>
|
||||
<label>
|
||||
<input
|
||||
onChange={handleOperationSelection}
|
||||
className={styles.display_inline + ' ' + styles.add_mar_right}
|
||||
type="checkbox"
|
||||
value="delete"
|
||||
checked={selectedOperations.delete}
|
||||
/>
|
||||
Delete
|
||||
</label>
|
||||
</div>
|
||||
{getColumnList('delete')}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const headersList = headers.map((header, i) => {
|
||||
@ -581,9 +442,6 @@ class AddTrigger extends Component {
|
||||
>
|
||||
<Operations
|
||||
dispatch={dispatch}
|
||||
supportManualTriggerInvocations={
|
||||
supportManualTriggerInvocations
|
||||
}
|
||||
enableManual={enableManual}
|
||||
selectedOperations={selectedOperations}
|
||||
handleOperationSelection={handleOperationSelection}
|
||||
@ -601,50 +459,37 @@ class AddTrigger extends Component {
|
||||
</OverlayTrigger>{' '}
|
||||
</h4>
|
||||
<div>
|
||||
{this.state.supportWebhookEnv ? (
|
||||
<div className={styles.dropdown_wrapper}>
|
||||
<DropdownButton
|
||||
dropdownOptions={[
|
||||
{ display_text: 'URL', value: 'url' },
|
||||
{ display_text: 'From env var', value: 'env' },
|
||||
]}
|
||||
title={
|
||||
(webhookUrlType === 'url' && 'URL') ||
|
||||
(webhookUrlType === 'env' && 'From env var') ||
|
||||
'Value'
|
||||
}
|
||||
dataKey={
|
||||
(webhookUrlType === 'url' && 'url') ||
|
||||
(webhookUrlType === 'env' && 'env')
|
||||
}
|
||||
onButtonChange={this.updateWebhookUrlType.bind(this)}
|
||||
onInputChange={e => {
|
||||
dispatch(setWebhookURL(e.target.value));
|
||||
}}
|
||||
required
|
||||
bsClass={styles.dropdown_button}
|
||||
inputVal={webhookURL}
|
||||
id="webhook-url"
|
||||
inputPlaceHolder={
|
||||
(webhookUrlType === 'url' &&
|
||||
'http://httpbin.org/post') ||
|
||||
(webhookUrlType === 'env' && 'MY_WEBHOOK_URL')
|
||||
}
|
||||
testId="webhook"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<input
|
||||
type="url"
|
||||
required
|
||||
data-test="webhook"
|
||||
placeholder="webhook url"
|
||||
className={`${styles.tableNameInput} form-control`}
|
||||
onChange={e => {
|
||||
<div className={styles.dropdown_wrapper}>
|
||||
<DropdownButton
|
||||
dropdownOptions={[
|
||||
{ display_text: 'URL', value: 'url' },
|
||||
{ display_text: 'From env var', value: 'env' },
|
||||
]}
|
||||
title={
|
||||
(webhookUrlType === 'url' && 'URL') ||
|
||||
(webhookUrlType === 'env' && 'From env var') ||
|
||||
'Value'
|
||||
}
|
||||
dataKey={
|
||||
(webhookUrlType === 'url' && 'url') ||
|
||||
(webhookUrlType === 'env' && 'env')
|
||||
}
|
||||
onButtonChange={this.updateWebhookUrlType.bind(this)}
|
||||
onInputChange={e => {
|
||||
dispatch(setWebhookURL(e.target.value));
|
||||
}}
|
||||
required
|
||||
bsClass={styles.dropdown_button}
|
||||
inputVal={webhookURL}
|
||||
id="webhook-url"
|
||||
inputPlaceHolder={
|
||||
(webhookUrlType === 'url' &&
|
||||
'http://httpbin.org/post') ||
|
||||
(webhookUrlType === 'env' && 'MY_WEBHOOK_URL')
|
||||
}
|
||||
testId="webhook"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<small>
|
||||
@ -713,32 +558,30 @@ class AddTrigger extends Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{supportRetryTimeout && (
|
||||
<div className={styles.retrySection}>
|
||||
<div className={`col-md-3 ${styles.padd_left_remove}`}>
|
||||
<label
|
||||
className={`${styles.add_mar_right} ${
|
||||
styles.retryLabel
|
||||
}`}
|
||||
>
|
||||
Timeout in seconds (default: 60)
|
||||
</label>
|
||||
</div>
|
||||
<div className={`col-md-6 ${styles.padd_left_remove}`}>
|
||||
<input
|
||||
onChange={e => {
|
||||
dispatch(setRetryTimeout(e.target.value));
|
||||
}}
|
||||
data-test="timeout-seconds"
|
||||
className={`${styles.display_inline} form-control ${
|
||||
styles.width300
|
||||
}`}
|
||||
type="text"
|
||||
placeholder="timeout in seconds"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.retrySection}>
|
||||
<div className={`col-md-3 ${styles.padd_left_remove}`}>
|
||||
<label
|
||||
className={`${styles.add_mar_right} ${
|
||||
styles.retryLabel
|
||||
}`}
|
||||
>
|
||||
Timeout in seconds (default: 60)
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
<div className={`col-md-6 ${styles.padd_left_remove}`}>
|
||||
<input
|
||||
onChange={e => {
|
||||
dispatch(setRetryTimeout(e.target.value));
|
||||
}}
|
||||
data-test="timeout-seconds"
|
||||
className={`${styles.display_inline} form-control ${
|
||||
styles.width300
|
||||
}`}
|
||||
type="text"
|
||||
placeholder="timeout in seconds"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div className={styles.add_mar_top}>
|
||||
|
@ -5,7 +5,6 @@ import * as tooltip from './Tooltips';
|
||||
import { TOGGLE_ENABLE_MANUAL_CONFIG } from './AddActions';
|
||||
|
||||
const Operations = ({
|
||||
supportManualTriggerInvocations,
|
||||
enableManual,
|
||||
selectedOperations,
|
||||
handleOperationSelection,
|
||||
@ -38,10 +37,6 @@ const Operations = ({
|
||||
];
|
||||
|
||||
const getManualInvokeOperation = () => {
|
||||
if (!supportManualTriggerInvocations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleManualOperationSelection = () => {
|
||||
dispatch({ type: TOGGLE_ENABLE_MANUAL_CONFIG });
|
||||
};
|
||||
@ -122,7 +117,6 @@ const Operations = ({
|
||||
};
|
||||
|
||||
Operations.propTypes = {
|
||||
supportManualTriggerInvocations: PropTypes.bool.isRequired,
|
||||
enableManual: PropTypes.bool.isRequired,
|
||||
selectedOperations: PropTypes.object.isRequired,
|
||||
handleOperationSelection: PropTypes.func.isRequired,
|
||||
|
@ -101,7 +101,7 @@ const loadTriggers = () => (dispatch, getState) => {
|
||||
type: LOAD_TRIGGER_LIST,
|
||||
triggerList: consistentTriggers || data[0],
|
||||
});
|
||||
dispatch(loadInconsistentObjects(null, false));
|
||||
dispatch(loadInconsistentObjects(false));
|
||||
},
|
||||
error => {
|
||||
console.error('Failed to load triggers' + JSON.stringify(error));
|
||||
|
@ -11,31 +11,13 @@ import OperationEditor from './OperationEditor';
|
||||
import RetryConfEditor from './RetryConfEditor';
|
||||
import HeadersEditor from './HeadersEditor';
|
||||
import ActionButtons from './ActionButtons';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
import { save, setDefaults, RESET_MODIFY_STATE } from './Actions';
|
||||
|
||||
class Modify extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
supportManualTriggerInvocations: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { serverVersion, dispatch } = this.props;
|
||||
const { dispatch } = this.props;
|
||||
dispatch(setDefaults());
|
||||
if (serverVersion) {
|
||||
this.checkSemver(serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { serverVersion } = nextProps;
|
||||
if (serverVersion && serverVersion !== this.props.serverVersion) {
|
||||
this.checkSemver(serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -45,16 +27,6 @@ class Modify extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
checkSemver(version) {
|
||||
this.checkManualTriggerInvocationSupport(version);
|
||||
}
|
||||
|
||||
checkManualTriggerInvocationSupport(version) {
|
||||
this.setState({
|
||||
supportManualTriggerInvocations: semverCheck('manualTriggers', version),
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
modifyTriggerName,
|
||||
@ -65,8 +37,6 @@ class Modify extends React.Component {
|
||||
tableSchemas,
|
||||
} = this.props;
|
||||
|
||||
const { supportManualTriggerInvocations } = this.state;
|
||||
|
||||
const currentTrigger = triggerList.find(
|
||||
tr => tr.name === modifyTriggerName
|
||||
);
|
||||
@ -123,7 +93,6 @@ class Modify extends React.Component {
|
||||
newDefinition={null}
|
||||
styles={styles}
|
||||
save={() => dispatch(save('ops', modifyTriggerName))}
|
||||
supportManualTriggerInvocations={supportManualTriggerInvocations}
|
||||
/>
|
||||
<RetryConfEditor
|
||||
retryConf={retry_conf}
|
||||
|
@ -5,8 +5,8 @@ import Tooltip from '../../../Common/Tooltip/Tooltip';
|
||||
import { toggleQueryType, toggleColumn, toggleManualType } from './Actions';
|
||||
|
||||
import {
|
||||
getValidQueryTypes,
|
||||
queryToInternalNameMap,
|
||||
getTriggerOperations,
|
||||
triggerOperationMap,
|
||||
MANUAL_TRIGGER_VAR,
|
||||
} from './utils';
|
||||
|
||||
@ -58,15 +58,14 @@ class OperationEditor extends React.Component {
|
||||
save,
|
||||
modifyTrigger,
|
||||
dispatch,
|
||||
supportManualTriggerInvocations,
|
||||
} = this.props;
|
||||
/*
|
||||
* Query types will have `CONSOLE_QUERY` only for version > 45
|
||||
*
|
||||
* */
|
||||
const queryTypes = getValidQueryTypes(supportManualTriggerInvocations);
|
||||
const operationTypes = getTriggerOperations();
|
||||
const renderOperation = (qt, i) => {
|
||||
const isChecked = Boolean(definition[queryToInternalNameMap[qt]]);
|
||||
const isChecked = Boolean(definition[triggerOperationMap[qt]]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -89,7 +88,7 @@ class OperationEditor extends React.Component {
|
||||
<div className={styles.modifyOps}>
|
||||
<div className={styles.modifyOpsCollapsedContent}>
|
||||
<div className={'col-md-12 ' + styles.padd_remove}>
|
||||
{queryTypes.map((qt, i) => renderOperation(qt, i))}
|
||||
{operationTypes.map((qt, i) => renderOperation(qt, i))}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.modifyOpsCollapsedContent}>
|
||||
@ -138,7 +137,7 @@ class OperationEditor extends React.Component {
|
||||
<div className={styles.modifyOpsPadLeft}>
|
||||
<div className={styles.modifyOpsCollapsedContent}>
|
||||
<div className={'col-md-12 ' + styles.padd_remove}>
|
||||
{queryTypes.map((qt, i) => (
|
||||
{operationTypes.map((qt, i) => (
|
||||
<div
|
||||
className={`${styles.opsCheckboxWrapper} col-md-2 ${
|
||||
styles.padd_remove
|
||||
@ -147,11 +146,9 @@ class OperationEditor extends React.Component {
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
this.toggleOperation({
|
||||
query: queryToInternalNameMap[qt],
|
||||
query: triggerOperationMap[qt],
|
||||
columns: allTableColumns.map(c => c.name),
|
||||
value: !modifyTrigger.definition[
|
||||
queryToInternalNameMap[qt]
|
||||
],
|
||||
value: !modifyTrigger.definition[triggerOperationMap[qt]],
|
||||
})
|
||||
);
|
||||
}}
|
||||
@ -160,7 +157,7 @@ class OperationEditor extends React.Component {
|
||||
type="checkbox"
|
||||
className={`${styles.opsCheckbox} ${styles.cursorPointer}`}
|
||||
checked={Boolean(
|
||||
modifyTrigger.definition[queryToInternalNameMap[qt]]
|
||||
modifyTrigger.definition[triggerOperationMap[qt]]
|
||||
)}
|
||||
/>
|
||||
{qt}
|
||||
|
@ -8,40 +8,15 @@ import {
|
||||
} from './Actions';
|
||||
import Tooltip from '../../../Common/Tooltip/Tooltip';
|
||||
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
|
||||
class RetryConfEditor extends React.Component {
|
||||
state = {
|
||||
supportRetryTimeout: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.serverVersion) {
|
||||
this.checkRetryTimeoutSupport(this.props.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.serverVersion !== this.props.serverVersion) {
|
||||
this.checkRetryTimeoutSupport(this.props.serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
setValues = () => {
|
||||
const { dispatch } = this.props;
|
||||
const retryConf = this.props.retryConf || {};
|
||||
dispatch(setRetryNum(retryConf.num_retries || 0));
|
||||
dispatch(setRetryInterval(retryConf.interval_sec || 10));
|
||||
if (this.state.supportRetryTimeout) {
|
||||
dispatch(setRetryTimeout(retryConf.timeout_sec || 60));
|
||||
}
|
||||
dispatch(setRetryTimeout(retryConf.timeout_sec || 60));
|
||||
};
|
||||
|
||||
checkRetryTimeoutSupport(version) {
|
||||
const supportRetryTimeout = semverCheck('triggerRetryTimeout', version);
|
||||
this.setState({ supportRetryTimeout });
|
||||
}
|
||||
|
||||
validateAndSave = () => {
|
||||
const {
|
||||
dispatch,
|
||||
@ -69,20 +44,19 @@ class RetryConfEditor extends React.Component {
|
||||
}
|
||||
dispatch(setRetryInterval(iRetryInterval));
|
||||
|
||||
if (this.state.supportRetryTimeout) {
|
||||
if (isNaN(iTimeout) || iTimeout <= 0) {
|
||||
dispatch(showValidationError('Timeout must be a positive number!'));
|
||||
return;
|
||||
}
|
||||
dispatch(setRetryTimeout(iTimeout));
|
||||
if (isNaN(iTimeout) || iTimeout <= 0) {
|
||||
dispatch(showValidationError('Timeout must be a positive number!'));
|
||||
return;
|
||||
}
|
||||
dispatch(setRetryTimeout(iTimeout));
|
||||
|
||||
this.props.save();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { styles, dispatch, modifyTrigger } = this.props;
|
||||
const retryConf = this.props.retryConf || {};
|
||||
const { supportRetryTimeout } = this.state;
|
||||
|
||||
const collapsed = () => (
|
||||
<div className={styles.modifyOps}>
|
||||
<div className={styles.modifyOpsCollapsedContent1}>
|
||||
@ -101,16 +75,12 @@ class RetryConfEditor extends React.Component {
|
||||
{retryConf.interval_sec || 10}
|
||||
</div>
|
||||
</div>
|
||||
{supportRetryTimeout && (
|
||||
<div className={styles.modifyOpsCollapsedContent1}>
|
||||
<div className={'col-md-4 ' + styles.padd_remove}>
|
||||
Timeout (sec):
|
||||
</div>
|
||||
<div className={'col-md-12 ' + styles.padd_remove}>
|
||||
{retryConf.timeout_sec || 60}
|
||||
</div>
|
||||
<div className={styles.modifyOpsCollapsedContent1}>
|
||||
<div className={'col-md-4 ' + styles.padd_remove}>Timeout (sec):</div>
|
||||
<div className={'col-md-12 ' + styles.padd_remove}>
|
||||
{retryConf.timeout_sec || 60}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -146,23 +116,21 @@ class RetryConfEditor extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{this.state.supportRetryTimeout && (
|
||||
<div className={styles.modifyOpsCollapsedContent1}>
|
||||
<div className={`col-md-4 ${styles.padd_remove}`}>
|
||||
Timeout (sec):
|
||||
</div>
|
||||
<div className="col-md-12">
|
||||
<input
|
||||
type="text"
|
||||
className={`${styles.input} form-control ${
|
||||
styles.add_mar_right
|
||||
} ${styles.modifyRetryConfTextbox}`}
|
||||
value={modifyTrigger.retryConf.timeout}
|
||||
onChange={e => dispatch(setRetryTimeout(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.modifyOpsCollapsedContent1}>
|
||||
<div className={`col-md-4 ${styles.padd_remove}`}>
|
||||
Timeout (sec):
|
||||
</div>
|
||||
)}
|
||||
<div className="col-md-12">
|
||||
<input
|
||||
type="text"
|
||||
className={`${styles.input} form-control ${
|
||||
styles.add_mar_right
|
||||
} ${styles.modifyRetryConfTextbox}`}
|
||||
value={modifyTrigger.retryConf.timeout}
|
||||
onChange={e => dispatch(setRetryTimeout(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -1,17 +1,11 @@
|
||||
export const MANUAL_TRIGGER_TEXT = 'Via console';
|
||||
export const MANUAL_TRIGGER_VAR = 'enable_manual';
|
||||
|
||||
export const getValidQueryTypes = supportManualTriggerInvocations => {
|
||||
const defaultQueryTypes = ['insert', 'update', 'delete'];
|
||||
|
||||
if (supportManualTriggerInvocations) {
|
||||
defaultQueryTypes.push(MANUAL_TRIGGER_TEXT);
|
||||
}
|
||||
|
||||
return defaultQueryTypes;
|
||||
export const getTriggerOperations = () => {
|
||||
return ['insert', 'update', 'delete', MANUAL_TRIGGER_TEXT];
|
||||
};
|
||||
|
||||
export const queryToInternalNameMap = {
|
||||
export const triggerOperationMap = {
|
||||
insert: 'insert',
|
||||
update: 'update',
|
||||
delete: 'delete',
|
||||
|
@ -7,7 +7,6 @@ import Tabs from 'react-bootstrap/lib/Tabs';
|
||||
import Tab from 'react-bootstrap/lib/Tab';
|
||||
import RedeliverEvent from '../TableCommon/RedeliverEvent';
|
||||
import TableHeader from '../TableCommon/TableHeader';
|
||||
import semverCheck from '../../../../helpers/semver';
|
||||
import parseRowData from './util';
|
||||
import {
|
||||
loadEventLogs,
|
||||
@ -38,41 +37,18 @@ class StreamingLogs extends Component {
|
||||
intervalId: null,
|
||||
filtered: [],
|
||||
filterAll: '',
|
||||
showRedeliver: false,
|
||||
};
|
||||
this.refreshData = this.refreshData.bind(this);
|
||||
this.filterAll = this.filterAll.bind(this);
|
||||
this.props.dispatch(setTrigger(this.props.triggerName));
|
||||
}
|
||||
componentDidMount() {
|
||||
if (this.props.serverVersion) {
|
||||
this.checkSemVer(this.props.serverVersion);
|
||||
}
|
||||
this.props.dispatch(setTrigger(this.props.triggerName));
|
||||
this.props.dispatch(loadEventLogs(this.props.triggerName));
|
||||
}
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.serverVersion !== this.props.serverVersion) {
|
||||
this.checkSemVer(nextProps.serverVersion);
|
||||
}
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.props.dispatch(vSetDefaults());
|
||||
}
|
||||
checkSemVer(version) {
|
||||
let showRedeliver = false;
|
||||
try {
|
||||
showRedeliver = semverCheck('eventRedeliver', version);
|
||||
if (showRedeliver) {
|
||||
this.setState({ showRedeliver: true });
|
||||
} else {
|
||||
this.setState({ showRedeliver: false });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.setState({ showRedeliver: false });
|
||||
}
|
||||
}
|
||||
handleNewerEvents() {
|
||||
// get the first element
|
||||
const firstElement = this.props.log.rows[0];
|
||||
@ -153,12 +129,10 @@ class StreamingLogs extends Component {
|
||||
|
||||
const invocationGridHeadings = [];
|
||||
invocationColumns.map(column => {
|
||||
if (!(column === 'redeliver' && !this.state.showRedeliver)) {
|
||||
invocationGridHeadings.push({
|
||||
Header: column,
|
||||
accessor: column,
|
||||
});
|
||||
}
|
||||
invocationGridHeadings.push({
|
||||
Header: column,
|
||||
accessor: column,
|
||||
});
|
||||
});
|
||||
|
||||
const invocationRowsData = [];
|
||||
@ -229,7 +203,7 @@ class StreamingLogs extends Component {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (col === 'redeliver' && this.state.showRedeliver) {
|
||||
if (col === 'redeliver') {
|
||||
return (
|
||||
<div className={conditionalClassname}>
|
||||
<i
|
||||
|
@ -3,7 +3,6 @@ import { push } from 'react-router-redux';
|
||||
import globals from '../../../Globals';
|
||||
import endpoints from '../../../Endpoints';
|
||||
import defaultState from './State';
|
||||
import semverCheck from '../../../helpers/semver';
|
||||
import { filterSchema } from './utils';
|
||||
import {
|
||||
setConsistentSchema,
|
||||
@ -62,21 +61,11 @@ export const filterInconsistentMetadata = (
|
||||
};
|
||||
|
||||
export const loadInconsistentObjects = (
|
||||
serverVersion,
|
||||
shouldReloadCache,
|
||||
successCb,
|
||||
failureCb
|
||||
) => {
|
||||
return (dispatch, getState) => {
|
||||
if (!semverCheck('inconsistentState', serverVersion)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!serverVersion) {
|
||||
const serverVersionFromState = getState().main.serverVersion;
|
||||
if (!semverCheck('inconsistentState', serverVersionFromState)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
const headers = getState().tables.dataHeaders;
|
||||
dispatch({ type: LOADING_METADATA });
|
||||
return dispatch(
|
||||
@ -130,38 +119,8 @@ export const loadInconsistentObjects = (
|
||||
};
|
||||
|
||||
export const reloadMetadata = (successCb, failureCb) => {
|
||||
return (dispatch, getState) => {
|
||||
const serverVersionFromState = getState().main.serverVersion;
|
||||
if (!semverCheck('inconsistentState', serverVersionFromState)) {
|
||||
const headers = getState().tables.dataHeaders;
|
||||
return dispatch(
|
||||
requestAction(endpoints.query, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(reloadCacheQuery),
|
||||
})
|
||||
).then(
|
||||
data => {
|
||||
if (successCb) {
|
||||
successCb(data);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
if (failureCb) {
|
||||
failureCb(error);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
return dispatch(
|
||||
loadInconsistentObjects(
|
||||
serverVersionFromState,
|
||||
true,
|
||||
successCb,
|
||||
failureCb
|
||||
)
|
||||
);
|
||||
return dispatch => {
|
||||
return dispatch(loadInconsistentObjects(true, successCb, failureCb));
|
||||
};
|
||||
};
|
||||
|
||||
@ -179,7 +138,7 @@ export const dropInconsistentObjects = () => {
|
||||
() => {
|
||||
dispatch({ type: DROPPED_INCONSISTENT_METADATA });
|
||||
dispatch(showSuccessNotification('Dropped inconsistent metadata'));
|
||||
dispatch(loadInconsistentObjects(null, false));
|
||||
dispatch(loadInconsistentObjects(false));
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
@ -510,7 +469,7 @@ export const metadataReducer = (state = defaultState, action) => {
|
||||
...state,
|
||||
allowedQueries: [
|
||||
...state.allowedQueries.map(q =>
|
||||
q.name === action.data.queryName ? action.data.newQuery : q
|
||||
(q.name === action.data.queryName ? action.data.newQuery : q)
|
||||
),
|
||||
],
|
||||
};
|
||||
|
@ -1,76 +1,15 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import semverCheck from '../../../helpers/semver';
|
||||
import React from 'react';
|
||||
import Sidebar from './Sidebar';
|
||||
import PageContainer from '../../Common/Layout/PageContainer/PageContainer';
|
||||
|
||||
const useMetadataSemver = serverVersion => {
|
||||
const [supportMetadata, setSupportMetadata] = useState(false);
|
||||
const [
|
||||
supportInconsistentMetadata,
|
||||
setSupportInconsistentMetadata,
|
||||
] = useState(false);
|
||||
const [supportAllowedQueries, setSupportAllowedQueries] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (serverVersion) {
|
||||
setSupportMetadata(semverCheck('metadataReload', serverVersion));
|
||||
}
|
||||
}, [serverVersion]);
|
||||
|
||||
useEffect(() => {
|
||||
if (serverVersion) {
|
||||
setSupportInconsistentMetadata(
|
||||
semverCheck('inconsistentState', serverVersion)
|
||||
);
|
||||
}
|
||||
}, [serverVersion]);
|
||||
|
||||
useEffect(() => {
|
||||
if (serverVersion) {
|
||||
setSupportAllowedQueries(semverCheck('allowedQueries', serverVersion));
|
||||
}
|
||||
}, [serverVersion]);
|
||||
|
||||
return {
|
||||
supportMetadata,
|
||||
supportInconsistentMetadata,
|
||||
supportAllowedQueries,
|
||||
};
|
||||
};
|
||||
|
||||
const Container = ({ location, serverVersion, children, metadata }) => {
|
||||
const {
|
||||
supportMetadata,
|
||||
supportInconsistentMetadata,
|
||||
supportAllowedQueries,
|
||||
} = useMetadataSemver(serverVersion);
|
||||
|
||||
if (!supportMetadata) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sidebar = (
|
||||
<Sidebar
|
||||
semverChecks={{
|
||||
supportMetadata,
|
||||
supportInconsistentMetadata,
|
||||
supportAllowedQueries,
|
||||
}}
|
||||
location={location}
|
||||
metadata={metadata}
|
||||
/>
|
||||
);
|
||||
|
||||
const Container = ({ location, children, metadata }) => {
|
||||
const helmet = 'Metadata | Hasura';
|
||||
|
||||
const childrenWithProps = React.Children.map(children, child =>
|
||||
React.cloneElement(child, {
|
||||
supportMetadata,
|
||||
supportInconsistentMetadata,
|
||||
metadata,
|
||||
})
|
||||
);
|
||||
const sidebar = <Sidebar location={location} metadata={metadata} />;
|
||||
|
||||
const childrenWithProps = React.Children.map(children, child =>
|
||||
React.cloneElement(child, { metadata })
|
||||
);
|
||||
return (
|
||||
<PageContainer helmet={helmet} leftContainer={sidebar}>
|
||||
{childrenWithProps}
|
||||
@ -83,7 +22,6 @@ const mapStateToProps = state => {
|
||||
...state.main,
|
||||
metadata: state.metadata,
|
||||
dataHeaders: { ...state.tables.dataHeaders },
|
||||
serverVersion: state.main.serverVersion,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,6 @@ import ClearAdminSecret from './ClearAdminSecret';
|
||||
import { CONSOLE_ADMIN_SECRET } from '../../../AppState';
|
||||
|
||||
const MetadataOptions = props => {
|
||||
const { supportMetadata } = props;
|
||||
const styles = require('../Metadata.scss');
|
||||
|
||||
const getMetadataImportExportSection = () => {
|
||||
@ -33,40 +32,34 @@ const MetadataOptions = props => {
|
||||
};
|
||||
|
||||
const getMetadataUpdateSection = () => {
|
||||
let updateSection = null;
|
||||
|
||||
if (supportMetadata) {
|
||||
updateSection = (
|
||||
<div>
|
||||
<div key="meta_data_1" className={styles.intro_note}>
|
||||
<h4>Reload metadata</h4>
|
||||
<div className={styles.content_width}>
|
||||
Refresh Hasura metadata, typically required if you have changed
|
||||
the underlying postgres.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div key="meta_data_2">
|
||||
<ReloadMetadata {...props} />
|
||||
</div>
|
||||
|
||||
<div key="meta_data_3" className={styles.intro_note}>
|
||||
<h4>Reset Metadata</h4>
|
||||
<div className={styles.content_width}>
|
||||
Permanently clear GraphQL Engine's metadata and configure it from
|
||||
scratch (tracking relevant tables and relationships). This process
|
||||
is not reversible.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div key="meta_data_4">
|
||||
<ResetMetadata {...props} />
|
||||
return (
|
||||
<div>
|
||||
<div key="meta_data_1" className={styles.intro_note}>
|
||||
<h4>Reload metadata</h4>
|
||||
<div className={styles.content_width}>
|
||||
Refresh Hasura metadata, typically required if you have changed the
|
||||
underlying postgres.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return updateSection;
|
||||
<div key="meta_data_2">
|
||||
<ReloadMetadata {...props} />
|
||||
</div>
|
||||
|
||||
<div key="meta_data_3" className={styles.intro_note}>
|
||||
<h4>Reset Metadata</h4>
|
||||
<div className={styles.content_width}>
|
||||
Permanently clear GraphQL Engine's metadata and configure it from
|
||||
scratch (tracking relevant tables and relationships). This process
|
||||
is not reversible.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div key="meta_data_4">
|
||||
<ResetMetadata {...props} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const getClearSecretSection = () => {
|
||||
@ -123,6 +116,7 @@ const MetadataOptions = props => {
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{getMetadataImportExportSection()}
|
||||
|
||||
{getMetadataUpdateSection()}
|
||||
|
@ -13,16 +13,12 @@ import CrossIcon from '../../../Common/Icons/Cross';
|
||||
|
||||
const MetadataStatus = ({
|
||||
dispatch,
|
||||
supportInconsistentMetadata,
|
||||
metadata,
|
||||
}) => {
|
||||
const [shouldShowErrorBanner, toggleErrorBanner] = useState(true);
|
||||
const dismissErrorBanner = () => {
|
||||
toggleErrorBanner(false);
|
||||
};
|
||||
if (!supportInconsistentMetadata) {
|
||||
return null;
|
||||
}
|
||||
const inconsistentObjectsTable = () => {
|
||||
return (
|
||||
<table
|
||||
@ -100,7 +96,7 @@ const MetadataStatus = ({
|
||||
};
|
||||
|
||||
const reloadCacheAndLoadInconsistentObjects = () => {
|
||||
dispatch(loadInconsistentObjects(null, true))
|
||||
dispatch(loadInconsistentObjects(true))
|
||||
.then(() => {
|
||||
dispatch(showSuccessNotification('Metadata reloaded'));
|
||||
})
|
||||
|
@ -5,43 +5,37 @@ import styles from '../../Common/TableCommon/Table.scss';
|
||||
import CheckIcon from '../../Common/Icons/Check';
|
||||
import CrossIcon from '../../Common/Icons/Cross';
|
||||
|
||||
const Sidebar = ({ location, semverChecks, metadata }) => {
|
||||
const Sidebar = ({ location, metadata }) => {
|
||||
const sectionsData = [];
|
||||
|
||||
if (semverChecks.supportMetadata) {
|
||||
sectionsData.push({
|
||||
key: 'actions',
|
||||
link: '/metadata/actions',
|
||||
dataTestVal: 'metadata-actions-link',
|
||||
title: 'Metadata Actions',
|
||||
});
|
||||
}
|
||||
sectionsData.push({
|
||||
key: 'actions',
|
||||
link: '/metadata/actions',
|
||||
dataTestVal: 'metadata-actions-link',
|
||||
title: 'Metadata Actions',
|
||||
});
|
||||
|
||||
if (semverChecks.supportInconsistentMetadata) {
|
||||
const consistentIcon =
|
||||
metadata.inconsistentObjects.length === 0 ? <CheckIcon /> : <CrossIcon />;
|
||||
const consistentIcon =
|
||||
metadata.inconsistentObjects.length === 0 ? <CheckIcon /> : <CrossIcon />;
|
||||
|
||||
sectionsData.push({
|
||||
key: 'status',
|
||||
link: '/metadata/status',
|
||||
dataTestVal: 'metadata-status-link',
|
||||
title: (
|
||||
<div className={styles.display_flex}>
|
||||
Metadata Status
|
||||
<span className={styles.add_mar_left}>{consistentIcon}</span>
|
||||
</div>
|
||||
),
|
||||
});
|
||||
}
|
||||
sectionsData.push({
|
||||
key: 'status',
|
||||
link: '/metadata/status',
|
||||
dataTestVal: 'metadata-status-link',
|
||||
title: (
|
||||
<div className={styles.display_flex}>
|
||||
Metadata Status
|
||||
<span className={styles.add_mar_left}>{consistentIcon}</span>
|
||||
</div>
|
||||
),
|
||||
});
|
||||
|
||||
if (semverChecks.supportAllowedQueries) {
|
||||
sectionsData.push({
|
||||
key: 'allowed-queries',
|
||||
link: '/metadata/allowed-queries',
|
||||
dataTestVal: 'metadata-allowed-queries-link',
|
||||
title: 'Allowed Queries',
|
||||
});
|
||||
}
|
||||
sectionsData.push({
|
||||
key: 'allowed-queries',
|
||||
link: '/metadata/allowed-queries',
|
||||
dataTestVal: 'metadata-allowed-queries-link',
|
||||
title: 'Allowed Queries',
|
||||
});
|
||||
|
||||
const currentLocation = location.pathname;
|
||||
|
||||
|
@ -1,25 +1,8 @@
|
||||
const semver = require('semver');
|
||||
|
||||
// list of feature launch versions
|
||||
const componentsSemver = {
|
||||
eventsTab: '1.0.0-alpha16',
|
||||
metadataReload: '1.0.0-alpha17',
|
||||
eventRedeliver: '1.0.0-alpha17',
|
||||
sqlAnalyze: '1.0.0-alpha25',
|
||||
aggregationPerm: '1.0.0-alpha26',
|
||||
supportColumnChangeTrigger: '1.0.0-alpha26',
|
||||
analyzeApiChange: '1.0.0-alpha26',
|
||||
insertPrefix: '1.0.0-alpha26',
|
||||
insertPermRestrictColumns: '1.0.0-alpha28',
|
||||
webhookEnvSupport: '1.0.0-alpha29',
|
||||
schemaStitching: '1.0.0-alpha30',
|
||||
permHideUpsertSection: '1.0.0-alpha32',
|
||||
customFunctionSection: '1.0.0-alpha36',
|
||||
triggerRetryTimeout: '1.0.0-alpha38',
|
||||
permUpdatePresets: '1.0.0-alpha38',
|
||||
tableColumnRename: '1.0.0-alpha39',
|
||||
inconsistentState: '1.0.0-alpha43',
|
||||
allowedQueries: '1.0.0-alpha46',
|
||||
manualTriggers: '1.0.0-alpha46',
|
||||
// feature: '1.0.1'
|
||||
};
|
||||
|
||||
const getPreRelease = version => {
|
||||
@ -27,6 +10,7 @@ const getPreRelease = version => {
|
||||
if (!prerelease) {
|
||||
return '';
|
||||
}
|
||||
// TODO: fix beta parsing
|
||||
if (prerelease.length === 1) {
|
||||
const regex = /(alpha|beta)(\d+)/gm;
|
||||
const str = prerelease[0];
|
||||
@ -95,4 +79,6 @@ const semverCheck = (component, serverVersion) => {
|
||||
return false;
|
||||
};
|
||||
|
||||
export { componentsSemver };
|
||||
|
||||
export default semverCheck;
|
||||
|
@ -50,7 +50,7 @@
|
||||
<div id="content" class="mainContent"></div>
|
||||
|
||||
<script>
|
||||
const assetsPathReadyEvent = new Event('assetsPathReadyEvent');
|
||||
// helper functions
|
||||
const loadIcon = (url) => {
|
||||
linkElem = document.createElement('link');
|
||||
linkElem.rel = 'icon';
|
||||
@ -72,41 +72,30 @@
|
||||
document.body.append(scriptElem);
|
||||
};
|
||||
const prependSlash = (str) => str === '' ? '' : '/' + str;
|
||||
document.body.addEventListener('assetsPathReadyEvent', (e) => {
|
||||
const loadAssets = () => {
|
||||
loadCSS(window.__env.assetsPath + '/common/css/font-awesome.min.css.gz');
|
||||
loadIcon(window.__env.assetsPath + '/common/img/hasura_icon_green.svg');
|
||||
loadCSS(window.__env.versionedAssetsPath + '/main.css.gz');
|
||||
loadScript(window.__env.versionedAssetsPath + '/main.js.gz');
|
||||
loadScript(window.__env.versionedAssetsPath + '/vendor.js.gz');
|
||||
|
||||
// remove this before merging.
|
||||
console.log(window.__env.assetsPath + '/common/css/font-awesome.min.css.gz');
|
||||
console.log(window.__env.assetsPath + '/common/img/hasura_icon_green.svg');
|
||||
console.log(window.__env.versionedAssetsPath + '/main.css.gz');
|
||||
console.log(window.__env.versionedAssetsPath + '/main.js.gz');
|
||||
console.log(window.__env.versionedAssetsPath + '/vendor.js.gz');
|
||||
}, false);
|
||||
};
|
||||
|
||||
// if cdnAssets is set to false, load assets from server instead of cdn
|
||||
if (window.__env.cdnAssets === false) {
|
||||
console.log('cdnAssets=false, loading assets from static-dir');
|
||||
window.__env.assetsPath =
|
||||
window.location.pathname.slice(
|
||||
0, window.location.pathname.lastIndexOf(window.__env.consolePath)
|
||||
) + '/console/assets';
|
||||
// set the path to get versioned assets from server
|
||||
window.__env.versionedAssetsPath = window.__env.assetsPath + '/versioned';
|
||||
// dispatch the event to load the assets now
|
||||
document.body.dispatchEvent(assetsPathReadyEvent);
|
||||
|
||||
// otherwise load from cdn itself
|
||||
} else {
|
||||
console.log('cdnAssets=true, loading assets from cdn');
|
||||
// set the path (cdn-based) to get assets from
|
||||
window.__env.versionedAssetsPath = window.__env.assetsPath + prependSlash(window.__env.assetsVersion);
|
||||
// fire the event
|
||||
document.body.dispatchEvent(assetsPathReadyEvent);
|
||||
}
|
||||
// load the assets now
|
||||
loadAssets();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user