Better payment notifications

This commit is contained in:
Gregory Schier 2016-11-17 15:22:23 -08:00
parent b05b144184
commit 3cbc43de6b
8 changed files with 99 additions and 16 deletions

View File

@ -20,7 +20,6 @@ export async function init (accountId) {
export function trackEvent (...args) {
try {
google.sendEvent(...args);
console.log(`[analytics] track ${args.join(', ')}`);
} catch (e) {
// Just to be extra safe
}
@ -29,7 +28,6 @@ export function trackEvent (...args) {
export function setAccountId (accountId) {
try {
google.setUserId(accountId);
console.log(`[analytics] account Id ${accountId}`);
} catch (e) {
// Just to be extra safe
}

View File

@ -9,7 +9,7 @@ class Nl2Br extends Component {
<p {...props}>{lines.map((l, i) => {
const trimmed = l.trim();
if (trimmed) {
const brs = i < lines.length - 1 ? [<br/>, <br/>] : [];
const brs = i < lines.length - 1 ? [<br/>] : [];
return [trimmed, ...brs];
} else {
return null;

View File

@ -9,6 +9,7 @@ import GenerateCodeModal from '../components/modals/GenerateCodeModal';
import PromptModal from '../components/modals/PromptModal';
import AlertModal from '../components/modals/AlertModal';
import PaymentModal from '../components/modals/PaymentModal';
import PaymentNotificationModal from '../components/modals/PaymentNotificationModal';
import ChangelogModal from '../components/modals/ChangelogModal';
import SyncLogsModal from '../components/modals/SyncLogsModal';
import LoginModal from '../components/modals/LoginModal';
@ -157,6 +158,7 @@ const Wrapper = props => {
<LoginModal ref={m => registerModal(m)}/>
<SignupModal ref={m => registerModal(m)}/>
<PaymentModal ref={m => registerModal(m)}/>
<PaymentNotificationModal ref={m => registerModal(m)}/>
<GenerateCodeModal
ref={m => registerModal(m)}
environmentId={activeEnvironment ? activeEnvironment._id : 'n/a'}

View File

@ -5,7 +5,7 @@ import SyncLogsModal from '../modals/SyncLogsModal';
import * as syncStorage from '../../../sync/storage';
import * as session from '../../../sync/session';
import * as sync from '../../../sync';
import * as analytics from '../../../analytics';
import {trackEvent} from '../../../analytics';
import SettingsModal, {TAB_PLUS} from '../modals/SettingsModal';
import LoginModal from '../modals/LoginModal';
import PromptButton from '../base/PromptButton';
@ -23,7 +23,7 @@ class SyncDropdown extends Component {
_handleHideMenu () {
this.setState({hide: true});
analytics.trackEvent('Sync', 'Hide Menu')
trackEvent('Sync', 'Hide Menu')
}
async _handleToggleSyncMode (resourceGroupId) {
@ -41,7 +41,7 @@ class SyncDropdown extends Component {
await this._handleSyncResourceGroupId(resourceGroupId);
}
analytics.trackEvent('Sync', 'Change Mode', syncMode);
trackEvent('Sync', 'Change Mode', syncMode);
}
async _handleSyncResourceGroupId (resourceGroupId) {
@ -57,7 +57,7 @@ class SyncDropdown extends Component {
// Unset loading state
this.setState({loading: false});
analytics.trackEvent('Sync', 'Manual Sync');
trackEvent('Sync', 'Manual Sync');
}
async _reloadData () {
@ -120,16 +120,24 @@ class SyncDropdown extends Component {
if (!loggedIn) {
return (
<div className={className}>
<Dropdown wide={true} className="wide tall">
<Dropdown wide={true}
className="wide tall"
onClick={e => trackEvent('Sync', 'Show Menu', 'Guest')}>
<DropdownButton className="btn btn--compact wide">
Sync Settings
</DropdownButton>
<DropdownDivider name="Insomnia Cloud Sync"/>
<DropdownItem onClick={e => showModal(SettingsModal, TAB_PLUS)}>
<DropdownItem onClick={e => {
showModal(SettingsModal, TAB_PLUS);
trackEvent('Sync', 'Create Account');
}}>
<i className="fa fa-user"></i>
Create Account
</DropdownItem>
<DropdownItem onClick={e => showModal(LoginModal)}>
<DropdownItem onClick={e => {
showModal(LoginModal);
trackEvent('Sync', 'Login');
}}>
<i className="fa fa-empty"></i>
Login
</DropdownItem>
@ -159,7 +167,9 @@ class SyncDropdown extends Component {
return (
<div className={className}>
<Dropdown wide={true} className="wide tall">
<Dropdown wide={true}
className="wide tall"
onClick={e => trackEvent('Sync', 'Show Menu', 'Authenticated')}>
<DropdownButton className="btn btn--compact wide">
{description}
</DropdownButton>

View File

@ -40,7 +40,8 @@ class PaymentModal extends Component {
}
}
show ({message, title}) {
show (options = {}) {
const {message, title} = options;
this.setState({error: '', message, title});
this.modal.show();
setTimeout(() => this._nameInput.focus(), 100);

View File

@ -0,0 +1,73 @@
import React, {Component} from 'react';
import Modal from '../base/Modal';
import ModalBody from '../base/ModalBody';
import ModalHeader from '../base/ModalHeader';
import ModalFooter from '../base/ModalFooter';
import PaymentModal from './PaymentModal';
import {showModal} from './index';
import * as session from '../../../sync/session';
import {trackEvent} from '../../../analytics';
let hidePaymentNotificationUntilNextLaunch = false;
class PaymentNotificationModal extends Component {
show () {
// Don't trigger automatically if user has dismissed it already
if (hidePaymentNotificationUntilNextLaunch) {
return;
}
hidePaymentNotificationUntilNextLaunch = true;
this.modal.show();
}
hide () {
trackEvent('Billing', 'Trial Ended', 'Cancel');
this.modal.hide();
}
render () {
return (
<Modal ref={m => this.modal = m}>
<ModalHeader>Free Trial has Ended</ModalHeader>
<ModalBody className="pad changelog">
<div className="text-center pad">
<h1>
Hi {session.getFirstName()},
</h1>
<p style={{maxWidth: '30rem', margin: 'auto'}}>
Your free trial has ended. please enter your billing information to
continue using Insomnia Plus.
</p>
<br/>
<p className="pad-top">
<button className="btn btn--compact btn--outlined" onClick={e => {
this.hide();
showModal(PaymentModal);
trackEvent('Billing', 'Trial Ended', 'Proceed')
}}>
Proceed to Billing
</button>
</p>
</div>
</ModalBody>
<ModalFooter>
<button className="btn" onClick={e => {
this.hide();
showModal(PaymentModal);
}}>Maybe Later
</button>
<div></div>
</ModalFooter>
</Modal>
)
}
}
PaymentNotificationModal.propTypes = {};
export default PaymentNotificationModal;

View File

@ -68,7 +68,7 @@ const SettingsSync = ({
$5 per month or $50 per year
<br/>
<span className="txt-sm faint pad-top-sm">
14-day trial (credit card required) cancel at any time
14-day trial (cancel at any time)
</span>
</p>
]}

View File

@ -6,7 +6,7 @@ import {importJSON, exportJSON} from '../../../export/database';
import {trackEvent} from '../../../analytics';
import AlertModal from '../../components/modals/AlertModal';
import {showModal} from '../../components/modals/index';
import PaymentModal from '../../components/modals/PaymentModal';
import PaymentNotificationModal from '../../components/modals/PaymentNotificationModal';
import LoginModal from '../../components/modals/LoginModal';
import * as models from '../../../models';
@ -97,8 +97,7 @@ export function newCommand (command, args) {
const {title, message} = args;
showModal(LoginModal, {title, message});
} else if (command === COMMAND_TRIAL_END) {
const {message, title} = args;
showModal(PaymentModal, {message, title});
showModal(PaymentNotificationModal);
}
return {type: command, ...args};