Skip to content
This repository has been archived by the owner on Jul 14, 2023. It is now read-only.

React users dashboard #205

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Pipfile
Expand Up @@ -20,7 +20,7 @@ psycopg2 = "==2.7.4"
redis = "==2.10.5"
requests = "==2.1.0"
SQLAlchemy = "==1.0.13"
stripe = "==1.55.0"
stripe = "==2.10.1"
structlog = "==16.1.0"
Flask = "==1"
Flask-CDN = "==1.5.3"
Expand Down
68 changes: 18 additions & 50 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 0 additions & 5 deletions formspree/forms/views.py
Expand Up @@ -488,11 +488,6 @@ def confirm_email(nonce):
return render_template('forms/email_confirmed.html', email=form.email, host=form.host)


@login_required
def serve_dashboard(hashid=None, s=None):
return render_template('forms/dashboard.html')


@login_required
def custom_template_preview_render():
body, _ = EmailTemplate.make_sample(
Expand Down
103 changes: 103 additions & 0 deletions formspree/js/Dashboard.js
@@ -0,0 +1,103 @@
/** @format */

const toastr = window.toastr
const fetch = window.fetch
const React = require('react')
const {StripeProvider} = require('react-stripe-elements')
const {
BrowserRouter: Router,
Route,
Redirect,
Switch,
Link
} = require('react-router-dom')

import Portal from './Portal'
import FormList from './forms/FormList'
import FormPage from './forms/FormPage'
import Account from './users/Account'
import Billing from './users/Billing'
import Plans from './users/Plans'

export const AccountContext = React.createContext()

export default class Dashboard extends React.Component {
constructor() {
super()

this.state = {
account: null
}
}

componentDidMount() {
Promise.all([
(async () => {
var r
try {
let resp = await fetch('/api-int/account', {
credentials: 'same-origin',
headers: {Accept: 'application/json'}
})
r = await resp.json()

if (!resp.ok || r.error) {
throw new Error(r.error || '')
}
} catch (e) {
if (location.pathname === '/plans') {
// ignore the fact that no user is registered.
this.setState({account: {}})
return
}

console.error(e)
this.setState({error: e.message})
toastr.error(
'Failed to fetch your account data. See the console for more details.'
)
return
}

this.setState({
account: {
user: r.user,
emails: r.emails,
sub: r.sub,
cards: r.cards,
invoices: r.invoices
}
})
})()
])
}

render() {
if (!this.state.account) {
return <p>loading...</p>
}

return (
<Router>
<StripeProvider apiKey={window.formspree.STRIPE_PUBLISHABLE_KEY}>
<AccountContext.Provider value={this.state.account}>
<Portal to="#forms-menu-item">
<Link to="/forms">Your forms</Link>
</Portal>
<Portal to="#account-menu-item">
<Link to="/account">Your account</Link>
</Portal>
<Switch>
<Redirect from="/dashboard" to="/forms" />
<Route exact path="/plans" component={Plans} />
<Route exact path="/account" component={Account} />
<Route exact path="/account/billing" component={Billing} />
<Route exact path="/forms" component={FormList} />
<Route path="/forms/:hashid" component={FormPage} />
</Switch>
</AccountContext.Provider>
</StripeProvider>
</Router>
)
}
}
11 changes: 7 additions & 4 deletions formspree/js/Portal.js
Expand Up @@ -5,9 +5,12 @@ const createPortal = require('react-dom').createPortal

export default class Portal extends React.Component {
render() {
return createPortal(
this.props.children,
document.querySelector(this.props.to)
)
let target = document.querySelector(this.props.to)

if (target) {
return createPortal(this.props.children, target)
} else {
return null
}
}
}
21 changes: 0 additions & 21 deletions formspree/js/forms/Dashboard.js

This file was deleted.

3 changes: 0 additions & 3 deletions formspree/js/forms/FormList.js
Expand Up @@ -85,9 +85,6 @@ export default class FormList extends React.Component {

return (
<>
<Portal to=".menu .item:nth-child(2)">
<Link to="/forms">Your forms</Link>
</Portal>
<Portal to="#header .center">
<h1>Your Forms</h1>
</Portal>
Expand Down
5 changes: 1 addition & 4 deletions formspree/js/forms/FormPage/index.js
Expand Up @@ -3,7 +3,7 @@
const toastr = window.toastr
const fetch = window.fetch
const React = require('react')
const {Route, Link, NavLink, Redirect} = require('react-router-dom')
const {Route, NavLink, Redirect} = require('react-router-dom')

import Portal from '../../Portal'
import Integration from './Integration'
Expand Down Expand Up @@ -32,9 +32,6 @@ export default class FormPage extends React.Component {

return (
<>
<Portal to=".menu .item:nth-child(2)">
<Link to="/forms">Your forms</Link>
</Portal>
<Portal to="#header .center">
<h1>Form Details</h1>
{this.state.form && (
Expand Down
13 changes: 0 additions & 13 deletions formspree/js/forms/main.js

This file was deleted.

2 changes: 1 addition & 1 deletion formspree/js/main.js
Expand Up @@ -77,7 +77,7 @@ $('a.resend').on('click', function() {
})

/* scripts at other files */
require('./forms/main.js')
require('./react-app.js')

/* toggle the card management menu */
$(function() {
Expand Down
18 changes: 18 additions & 0 deletions formspree/js/react-app.js
@@ -0,0 +1,18 @@
/** @format */

const render = require('react-dom').render
const React = require('react') // eslint-disable-line no-unused-vars

import Dashboard from './Dashboard'

if (document.querySelector('body.dashboard')) {
if (location.pathname !== '/plan') {
let fmi = document.getElementById('forms-menu-item')
let ami = document.getElementById('account-menu-item')
if (fmi) fmi.innerHTML = ''
if (ami) ami.innerHTML = ''
}

let el = document.getElementById('react-app')
render(<Dashboard />, el)
}