这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions console/src/components/Main/Actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const setFeaturesCompatibility = data => ({
data,
});

const PRO_CLICKED = 'Main/PRO_CLICKED';
const emitProClickedEvent = data => ({
type: PRO_CLICKED,
data,
});

const SET_READ_ONLY_MODE = 'Main/SET_READ_ONLY_MODE';
const setReadOnlyMode = data => ({
type: SET_READ_ONLY_MODE,
Expand Down Expand Up @@ -317,6 +323,7 @@ export {
updateMigrationModeStatus,
LOGIN_IN_PROGRESS,
LOGIN_ERROR,
emitProClickedEvent,
loadServerVersion,
fetchServerConfig,
loadLatestServerVersion,
Expand Down
153 changes: 147 additions & 6 deletions console/src/components/Main/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
fetchServerConfig,
loadLatestServerVersion,
featureCompatibilityInit,
emitProClickedEvent,
} from './Actions';

import { loadConsoleTelemetryOpts } from '../../telemetry/Actions.js';
Expand All @@ -28,7 +29,9 @@ import {
import {
getLoveConsentState,
setLoveConsentState,
} from './loveConsentLocalStorage';
getProClickState,
setProClickState,
} from './utils';

import { versionGT } from '../../helpers/versionUtils';
import { getSchemaBaseRoute } from '../Common/utils/routesUtils';
Expand All @@ -40,11 +43,12 @@ class Main extends React.Component {
this.state = {
showUpdateNotification: false,
loveConsentState: getLoveConsentState(),
proClickState: getProClickState(),
isPopUpOpen: false,
};

this.handleBodyClick = this.handleBodyClick.bind(this);
}

componentDidMount() {
const { dispatch } = this.props;

Expand All @@ -58,7 +62,6 @@ class Main extends React.Component {
dispatch(loadInconsistentObjects()).then(() => {
this.handleMetadataRedirect();
});

dispatch(loadConsoleTelemetryOpts());

dispatch(loadLatestServerVersion()).then(() => {
Expand All @@ -68,7 +71,11 @@ class Main extends React.Component {

dispatch(fetchServerConfig());
}

toggleProPopup() {
const { dispatch } = this.props;
dispatch(emitProClickedEvent({ open: !this.state.isPopUpOpen }));
this.setState({ isPopUpOpen: !this.state.isPopUpOpen });
}
setShowUpdateNotification() {
const { latestServerVersion, serverVersion } = this.props;

Expand Down Expand Up @@ -125,7 +132,22 @@ class Main extends React.Component {
loveConsentState: { ...getLoveConsentState() },
});
}
updateLocalStorageState() {
const s = getProClickState();
if (s && 'isProClicked' in s && !s.isProClicked) {
setProClickState({
isProClicked: !s.isProClicked,
});
this.setState({
proClickState: { ...getProClickState() },
});
}
}

clickProIcon() {
this.updateLocalStorageState();
this.toggleProPopup();
}
closeUpdateBanner() {
const { latestServerVersion } = this.props;
window.localStorage.setItem(
Expand All @@ -146,6 +168,8 @@ class Main extends React.Component {
metadata,
} = this.props;

const { isProClicked } = this.state.proClickState;

const styles = require('./Main.scss');

const appPrefix = '';
Expand All @@ -157,7 +181,13 @@ class Main extends React.Component {
const docs = require('./images/docs-logo.svg');
const about = require('./images/console-logo.svg');
const pixHeart = require('./images/pix-heart.svg');

const close = require('./images/x-circle.svg');
const monitoring = require('./images/monitoring.svg');
const rate = require('./images/rate.svg');
const regression = require('./images/regression.svg');
const management = require('./images/management.svg');
const allow = require('./images/allow.svg');
const arrowForwardRed = require('./images/arrow_forward-red.svg');
const currentLocation = location.pathname;
const currentActiveBlock = getPathRoot(currentLocation);

Expand Down Expand Up @@ -437,6 +467,107 @@ class Main extends React.Component {
);
};

const renderProPopup = () => {
const { isPopUpOpen } = this.state;
if (isPopUpOpen) {
return (
<div className={styles.proPopUpWrapper}>
<div className={styles.popUpHeader}>
Hasura <span>PRO</span>
<img
onClick={this.toggleProPopup.bind(this)}
className={styles.popUpClose}
src={close}
alt={'Close'}
/>
</div>
<div className={styles.popUpBodyWrapper}>
<div className={styles.featuresDescription}>
Hasura Pro is an enterprise-ready version of Hasura that comes
with the following features:
</div>
<div className={styles.proFeaturesList}>
<div className={styles.featuresImg}>
<img src={monitoring} alt={'Monitoring'} />
</div>
<div className={styles.featuresList}>
<div className={styles.featuresTitle}>
Monitoring/Analytics
</div>
<div className={styles.featuresDescription}>
Complete observability: Troubleshoot errors & drill-down
into individual operations.
</div>
</div>
</div>
<div className={styles.proFeaturesList}>
<div className={styles.featuresImg}>
<img src={rate} alt={'Rate'} />
</div>
<div className={styles.featuresList}>
<div className={styles.featuresTitle}>Rate Limiting</div>
<div className={styles.featuresDescription}>
Role-based rate limits to prevent abuse.
</div>
</div>
</div>
<div className={styles.proFeaturesList}>
<div className={styles.featuresImg}>
<img src={regression} alt={'Regression'} />
</div>
<div className={styles.featuresList}>
<div className={styles.featuresTitle}>Regression Testing</div>
<div className={styles.featuresDescription}>
Automatically create regression suites to prevent breaking
changes.
</div>
</div>
</div>
<div className={styles.proFeaturesList}>
<div className={styles.featuresImg}>
<img src={management} alt={'Management'} />
</div>
<div className={styles.featuresList}>
<div className={styles.featuresTitle}>Team Management</div>
<div className={styles.featuresDescription}>
Login to a Hasura project with granular privileges.
</div>
</div>
</div>
<div className={styles.proFeaturesList}>
<div className={styles.featuresImg}>
<img src={allow} alt={'allow'} />
</div>
<div className={styles.featuresList}>
<div className={styles.featuresTitle}>Allow Listing</div>
<div className={styles.featuresDescription}>
Easy workflows to setup allow lists across dev, staging and
production environments.
</div>
</div>
</div>
</div>
<div className={styles.popUpFooter}>
<a
href={
'https://hasura.io/getintouch?type=hasuraprodemo&utm_source=console'
}
target={'_blank'}
>
Set up a chat with us to learn more{' '}
<img
className={styles.arrow}
src={arrowForwardRed}
alt={'Arrow'}
/>
</a>
</div>
</div>
);
}
return null;
};

return (
<div className={styles.container}>
<div className={styles.flexRow}>
Expand Down Expand Up @@ -484,7 +615,17 @@ class Main extends React.Component {
</div>
<div id="dropdown_wrapper" className={styles.clusterInfoWrapper}>
{getAdminSecretSection()}

<div className={styles.helpSection + ' ' + styles.proWrapper}>
<span
className={
!isProClicked ? styles.proName : styles.proNameClicked
}
onClick={this.clickProIcon.bind(this)}
>
PRO
</span>
{renderProPopup()}
</div>
<Link to="/settings">
<div className={styles.helpSection + ' ' + styles.settingsIcon}>
{getMetadataStatusIcon()}
Expand Down
108 changes: 106 additions & 2 deletions console/src/components/Main/Main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
}

.header_items {
width: 50%;
width: 45%;
}

.header_logo_wrapper {
Expand Down Expand Up @@ -145,7 +145,7 @@
}

.clusterInfoWrapper {
width: 30%;
width: 35%;
display: flex;
justify-content: flex-end;
position: relative;
Expand Down Expand Up @@ -1203,3 +1203,107 @@
left: 4px;
z-index: -1;
}
/* PRO popup section */
.proWrapper {
position: relative;
padding: 12px 15px;
.proName, .proNameClicked {
font-size: 15px;
font-weight: bold;
font-stretch: normal;
font-style: normal;
line-height: 1.6;
letter-spacing: 1px;
cursor: pointer;
&:hover {
opacity: .8;
}
}
.proName {
color: #1cd3c6;
}
.proNameClicked {
color: #fff;
}
.proPopUpWrapper {
position: absolute;
box-shadow: 0 3px 20px 0 rgba(0, 0, 0, 0.24);
background-color: #ffffff;
position: absolute;
width: 540px;
z-index: 1;
top: 60px;
right: -35px;
text-transform: none;
overflow: auto;
max-height: calc(100vh - 80px);
.popUpHeader {
font-size: 20px;
font-weight: bold;
color: #001934;
background-color: #f8f8f8;
padding: 20px 24px;
border-bottom: 1px solid #ddd;
span {
color: #1cd3c6;
}
.popUpClose {
position: absolute;
top: 28px;
right: 24px;
cursor: pointer;
&:hover {
opacity: .8;
}
}
}
.popUpBodyWrapper {
padding: 24px 24px;
padding-bottom: 0;
.featuresDescription {
padding-bottom: 24px;
font-size: 15px;
color: #303030;
font-weight: normal;
}
.proFeaturesList {
display: flex;
.featuresImg {
padding-right: 14px;
}
.featuresList {
.featuresTitle {
font-size: 15px;
font-weight: bold;
color: #303030;
padding-bottom: 8px;
}
.featuresDescription {
opacity: .6;
}
}
}
}
.popUpFooter {
border-top: 1px solid #ddd;
padding: 20px 24px;
color: #ff3264;
font-weight: normal;
font-size: 15px;
a {
color: #ff3264;
&:hover {
text-decoration: none;
border-bottom: 1px solid #ff3264;
}
&:focus {
outline: none;
text-decoration: none;
}
}
.arrow {
margin-left: 8px;
}
}
}
}
15 changes: 15 additions & 0 deletions console/src/components/Main/images/allow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading