improve version check for server dependent features (close #388) (#676)

This commit is contained in:
Aravind Shankar 2018-10-09 16:33:48 +05:30 committed by Shahidh K Muhammed
parent 603461ad8f
commit a68bb61250
5 changed files with 358 additions and 241 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ import 'react-toggle/style.css';
import Spinner from '../Common/Spinner/Spinner'; import Spinner from '../Common/Spinner/Spinner';
import { loadServerVersion, checkServerUpdates } from './Actions'; import { loadServerVersion, checkServerUpdates } from './Actions';
import './NotificationOverrides.css'; import './NotificationOverrides.css';
import semverCheck from '../../helpers/semver';
const semver = require('semver'); const semver = require('semver');
@ -36,26 +37,23 @@ class Main extends React.Component {
dispatch(checkServerUpdates()).then(() => { dispatch(checkServerUpdates()).then(() => {
let isUpdateAvailable = false; let isUpdateAvailable = false;
try { try {
if ( const showEvents = semverCheck('eventsTab', this.props.serverVersion);
semver.valid(this.props.serverVersion) === null || console.log(showEvents);
semver.gt(this.props.serverVersion, '1.0.0-alpha15') if (showEvents) {
) {
this.setState({ showEvents: true }); this.setState({ showEvents: true });
}
isUpdateAvailable = semver.gt(
this.props.latestServerVersion,
this.props.serverVersion
);
const isClosedBefore = window.localStorage.getItem(
this.props.latestServerVersion + '_BANNER_NOTIFICATION_CLOSED'
);
if (isClosedBefore === 'true') {
isUpdateAvailable = false;
this.setState({ showBannerNotification: false });
} else { } else {
this.setState({ showEvents: false }); this.setState({ showBannerNotification: isUpdateAvailable });
isUpdateAvailable = semver.gt(
this.props.latestServerVersion,
this.props.serverVersion
);
const isClosedBefore = window.localStorage.getItem(
this.props.latestServerVersion + '_BANNER_NOTIFICATION_CLOSED'
);
if (isClosedBefore === 'true') {
isUpdateAvailable = false;
this.setState({ showBannerNotification: false });
} else {
this.setState({ showBannerNotification: isUpdateAvailable });
}
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -314,30 +312,30 @@ class Main extends React.Component {
</div> </div>
{!this.state.loveConsentState.isDismissed {!this.state.loveConsentState.isDismissed
? [ ? [
<div <div
key="main_love_1" key="main_love_1"
className={styles.shareSection + ' dropdown-toggle'} className={styles.shareSection + ' dropdown-toggle'}
aria-expanded="false" aria-expanded="false"
onClick={this.handleDropdownToggle.bind(this)} onClick={this.handleDropdownToggle.bind(this)}
> >
<img <img
className={'img-responsive'} className={'img-responsive'}
src={pixHeart} src={pixHeart}
alt={'pix Heart'} alt={'pix Heart'}
/> />
{/* <i className={styles.heart + ' fa fa-heart'} /> */} {/* <i className={styles.heart + ' fa fa-heart'} /> */}
</div>, </div>,
<ul <ul
key="main_love_2" key="main_love_2"
className={'dropdown-menu ' + styles.dropdown_menu} className={'dropdown-menu ' + styles.dropdown_menu}
> >
<div className={styles.dropdown_menu_container}> <div className={styles.dropdown_menu_container}>
<div className={styles.closeDropDown}> <div className={styles.closeDropDown}>
<i <i
className="fa fa-close" className="fa fa-close"
onClick={this.closeLoveIcon.bind(this)} onClick={this.closeLoveIcon.bind(this)}
/> />
{/* {/*
<img <img
className={'img-responsive'} className={'img-responsive'}
src={closeIcon} src={closeIcon}
@ -345,8 +343,8 @@ class Main extends React.Component {
onClick={this.closeLoveIcon.bind(this)} onClick={this.closeLoveIcon.bind(this)}
/> />
*/} */}
</div> </div>
{/* {/*
<div className={styles.arrow_up_dropdown} /> <div className={styles.arrow_up_dropdown} />
<div className={styles.graphqlHeartText}> <div className={styles.graphqlHeartText}>
Love GraphQL Engine? Shout it from the rooftops! Love GraphQL Engine? Shout it from the rooftops!
@ -357,37 +355,37 @@ class Main extends React.Component {
</span> </span>
</div> </div>
*/} */}
<div className={styles.displayFlex}> <div className={styles.displayFlex}>
<li className={styles.pixelText1}> <li className={styles.pixelText1}>
Roses are red, <br /> Roses are red, <br />
Violets are blue; Violets are blue;
<br /> <br />
Star us on Github, Star us on Github,
<br /> <br />
To make our <i className={'fa fa-heart'} /> go To make our <i className={'fa fa-heart'} /> go
wooooo! wooooo!
</li> </li>
<li className={'dropdown-item'}> <li className={'dropdown-item'}>
<a <a
href="https://github.com/hasura/graphql-engine" href="https://github.com/hasura/graphql-engine"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<div className={styles.socialIcon}> <div className={styles.socialIcon}>
<img <img
className="img img-responsive" className="img img-responsive"
src={ src={
'https://storage.googleapis.com/hasura-graphql-engine/console/assets/githubicon.png' 'https://storage.googleapis.com/hasura-graphql-engine/console/assets/githubicon.png'
} }
alt={'Github'} alt={'Github'}
/> />
</div> </div>
<div className={styles.pixelText}> <div className={styles.pixelText}>
<i className="fa fa-star" /> <i className="fa fa-star" />
&nbsp; Star &nbsp; Star
</div> </div>
</a> </a>
{/* {/*
<div className={styles.gitHubBtn}> <div className={styles.gitHubBtn}>
<iframe <iframe
title="github" title="github"
@ -399,32 +397,32 @@ class Main extends React.Component {
/> />
</div> </div>
*/} */}
</li> </li>
<li className={'dropdown-item '}> <li className={'dropdown-item '}>
<a <a
href="https://twitter.com/intent/tweet?hashtags=graphql,postgres&text=Just%20deployed%20a%20GraphQL%20backend%20with%20@HasuraHQ!%20%E2%9D%A4%EF%B8%8F%20%F0%9F%9A%80%0Ahttps://github.com//hasura/graphql-engine%0A" href="https://twitter.com/intent/tweet?hashtags=graphql,postgres&text=Just%20deployed%20a%20GraphQL%20backend%20with%20@HasuraHQ!%20%E2%9D%A4%EF%B8%8F%20%F0%9F%9A%80%0Ahttps://github.com//hasura/graphql-engine%0A"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<div className={styles.socialIcon}> <div className={styles.socialIcon}>
<img <img
className="img img-responsive" className="img img-responsive"
src={ src={
'https://storage.googleapis.com/hasura-graphql-engine/console/assets/twittericon.png' 'https://storage.googleapis.com/hasura-graphql-engine/console/assets/twittericon.png'
} }
alt={'Twitter'} alt={'Twitter'}
/> />
</div> </div>
<div className={styles.pixelText}> <div className={styles.pixelText}>
<i className="fa fa-twitter" /> <i className="fa fa-twitter" />
&nbsp; Tweet &nbsp; Tweet
</div> </div>
</a> </a>
</li> </li>
</div>
</div> </div>
</ul>, </div>
] </ul>,
]
: null} : null}
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@ import ImportMetadata from './ImportMetadata';
import ReloadMetadata from './ReloadMetadata'; import ReloadMetadata from './ReloadMetadata';
import ClearAccessKey from './ClearAccessKey'; import ClearAccessKey from './ClearAccessKey';
const semver = require('semver'); import semverCheck from '../../../../helpers/semver';
class Metadata extends Component { class Metadata extends Component {
constructor() { constructor() {
@ -28,11 +28,8 @@ class Metadata extends Component {
} }
checkSemVer(version) { checkSemVer(version) {
try { try {
// If version is invalid semver or current version is greater than 1.0.0-alpha16, display Reload Metadata button const showMetadata = semverCheck('metadataReload', version);
if ( if (showMetadata) {
semver.valid(version) === null ||
semver.gt(version, '1.0.0-alpha16')
) {
this.updateMetadataState(true); this.updateMetadataState(true);
} else { } else {
this.updateMetadataState(false); this.updateMetadataState(false);

View File

@ -7,6 +7,7 @@ import Tabs from 'react-bootstrap/lib/Tabs';
import Tab from 'react-bootstrap/lib/Tab'; import Tab from 'react-bootstrap/lib/Tab';
import RedeliverEvent from '../TableCommon/RedeliverEvent'; import RedeliverEvent from '../TableCommon/RedeliverEvent';
import TableHeader from '../TableCommon/TableHeader'; import TableHeader from '../TableCommon/TableHeader';
import semverCheck from '../../../../helpers/semver';
import { import {
loadEventLogs, loadEventLogs,
setTrigger, setTrigger,
@ -32,18 +33,41 @@ class StreamingLogs extends Component {
intervalId: null, intervalId: null,
filtered: [], filtered: [],
filterAll: '', filterAll: '',
showRedeliver: false,
}; };
this.refreshData = this.refreshData.bind(this); this.refreshData = this.refreshData.bind(this);
this.filterAll = this.filterAll.bind(this); this.filterAll = this.filterAll.bind(this);
this.props.dispatch(setTrigger(this.props.triggerName)); this.props.dispatch(setTrigger(this.props.triggerName));
} }
componentDidMount() { componentDidMount() {
if (this.props.serverVersion) {
this.checkSemVer(this.props.serverVersion);
}
this.props.dispatch(setTrigger(this.props.triggerName)); this.props.dispatch(setTrigger(this.props.triggerName));
this.props.dispatch(loadEventLogs(this.props.triggerName)); this.props.dispatch(loadEventLogs(this.props.triggerName));
} }
componentWillReceiveProps(nextProps) {
if (nextProps.serverVersion !== this.props.serverVersion) {
this.checkSemVer(nextProps.serverVersion);
}
}
componentWillUnmount() { componentWillUnmount() {
this.props.dispatch(vSetDefaults()); this.props.dispatch(vSetDefaults());
} }
checkSemVer(version) {
let showRedeliver = false;
try {
showRedeliver = semverCheck('eventRedeliver', version);
if (showRedeliver) {
this.setState({ ...this.state, showRedeliver: true });
} else {
this.setState({ ...this.state, showRedeliver: false });
}
} catch (e) {
console.log(e);
this.setState({ ...this.state, showRedeliver: false });
}
}
handleNewerEvents() { handleNewerEvents() {
// get the first element // get the first element
const firstElement = this.props.log.rows[0]; const firstElement = this.props.log.rows[0];
@ -122,10 +146,12 @@ class StreamingLogs extends Component {
]; ];
const invocationGridHeadings = []; const invocationGridHeadings = [];
invocationColumns.map(column => { invocationColumns.map(column => {
invocationGridHeadings.push({ if (!(column === 'redeliver' && !this.state.showRedeliver)) {
Header: column, invocationGridHeadings.push({
accessor: column, Header: column,
}); accessor: column,
});
}
}); });
invocationGridHeadings.push({ invocationGridHeadings.push({
// NOTE - this is a "filter all" DUMMY column // NOTE - this is a "filter all" DUMMY column
@ -222,7 +248,7 @@ class StreamingLogs extends Component {
</div> </div>
); );
} }
if (col === 'redeliver') { if (col === 'redeliver' && this.state.showRedeliver) {
return ( return (
<div className={conditionalClassname}> <div className={conditionalClassname}>
<i <i
@ -407,6 +433,7 @@ StreamingLogs.propTypes = {
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
return { return {
...state.triggers, ...state.triggers,
serverVersion: state.main.serverVersion,
triggerName: ownProps.params.trigger, triggerName: ownProps.params.trigger,
migrationMode: state.main.migrationMode, migrationMode: state.main.migrationMode,
currentSchema: state.tables.currentSchema, currentSchema: state.tables.currentSchema,

View File

@ -0,0 +1,81 @@
const semver = require('semver');
const componentsSemver = {
eventsTab: '1.0.0-alpha16',
metadataReload: '1.0.0-alpha17',
eventRedeliver: '1.0.0-alpha17',
};
const getPreRelease = version => {
const prerelease = semver.prerelease(version);
if (prerelease.length === 1) {
const regex = /(alpha|beta)(\d+)/gm;
const str = prerelease[0];
const m = regex.exec(str);
if (m.length < 3) {
return [];
}
return m.slice(1, 3);
}
return prerelease.slice(0, 2);
};
const semverCheck = (component, serverVersion) => {
if (component in componentsSemver) {
const componentCoerce = semver.valid(
semver.coerce(componentsSemver[component])
);
if (componentCoerce == null) {
return false;
}
const serverCoerce = semver.valid(semver.coerce(serverVersion));
if (serverCoerce == null) {
return true;
}
switch (semver.compare(serverCoerce, componentCoerce)) {
case 0:
// check for prerelease tags
const componentPrerelease = getPreRelease(componentsSemver[component]);
const serverPrerelease = getPreRelease(serverVersion);
// If both component and server doesn't have a prerelease, return true
if (componentPrerelease.length === 0 && serverPrerelease.length === 0) {
return true;
}
// If component does't have a prerelease tag and server has a p rerelease
// tag, return false
if (componentPrerelease.length === 0 && serverPrerelease.length !== 0) {
return false;
}
// If server does't have a prerelease tag and component has a prerelease
// tag, return true
if (componentPrerelease.length !== 0 && serverPrerelease.length === 0) {
return true;
}
if (
componentPrerelease[0] === 'beta' &&
serverPrerelease[0] !== 'beta'
) {
return false;
}
if (
parseInt(serverPrerelease[1], 10) >=
parseInt(componentPrerelease[1], 10)
) {
return true;
}
return false;
case 1:
return true;
case -1:
return false;
default:
return false;
}
}
return false;
};
export default semverCheck;