mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 07:38:07 -05:00
Merge pull request #139 from rschamp/feature/email-confirmation-banner
Add email confirmation banner to homepage
This commit is contained in:
commit
b7f795f2d9
7 changed files with 195 additions and 55 deletions
29
src/components/banner/banner.jsx
Normal file
29
src/components/banner/banner.jsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
|
||||
require('./banner.scss');
|
||||
|
||||
var Banner = React.createClass({
|
||||
type: 'Banner',
|
||||
propTypes: {
|
||||
onRequestDismiss: React.PropTypes.func
|
||||
},
|
||||
render: function () {
|
||||
var classes = classNames(
|
||||
'banner',
|
||||
this.props.className
|
||||
);
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className="inner">
|
||||
{this.props.children}
|
||||
{this.props.onRequestDismiss ? [
|
||||
<a className="close" key="close" href="#" onClick={this.props.onRequestDismiss}>x</a>
|
||||
] : []}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Banner;
|
41
src/components/banner/banner.scss
Normal file
41
src/components/banner/banner.scss
Normal file
|
@ -0,0 +1,41 @@
|
|||
@import "../../colors";
|
||||
|
||||
$navigation-height: 50px;
|
||||
|
||||
.banner {
|
||||
position: fixed;
|
||||
top: $navigation-height;
|
||||
z-index: 99;
|
||||
box-shadow: 0 1px 1px $ui-dark-gray;
|
||||
background-color: $ui-orange;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
line-height: $navigation-height;
|
||||
|
||||
&, a {
|
||||
color: $ui-white;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.close {
|
||||
float: right;
|
||||
margin-top: $navigation-height/4;
|
||||
border-radius: $navigation-height/4;
|
||||
background-color: $box-shadow-gray;
|
||||
width: $navigation-height/2;
|
||||
height: $navigation-height/2;
|
||||
text-decoration: none;
|
||||
text-shadow: none;
|
||||
line-height: $navigation-height/2;
|
||||
color: $ui-white;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
&.warning {
|
||||
background-color: $ui-orange;
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
|
||||
require('./box.scss');
|
||||
|
@ -11,8 +12,12 @@ var Box = React.createClass({
|
|||
moreProps: React.PropTypes.object
|
||||
},
|
||||
render: function () {
|
||||
var classes = classNames(
|
||||
'box',
|
||||
this.props.className
|
||||
);
|
||||
return (
|
||||
<div className={'box ' + this.props.className}>
|
||||
<div className={classes}>
|
||||
<div className="box-header">
|
||||
<h4>{this.props.title}</h4>
|
||||
<p>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
var classNames = require('classnames');
|
||||
var defaults = require('lodash.defaults');
|
||||
var React = require('react');
|
||||
var Slider = require('react-slick');
|
||||
|
@ -31,9 +32,12 @@ var Carousel = React.createClass({
|
|||
variableWidth: true
|
||||
});
|
||||
var arrows = this.props.items.length > settings.slidesToShow;
|
||||
|
||||
var classes = classNames(
|
||||
'carousel',
|
||||
this.props.className
|
||||
);
|
||||
return (
|
||||
<Slider className={'carousel ' + this.props.className} arrows={arrows} {... settings}>
|
||||
<Slider className={classes} arrows={arrows} {... settings}>
|
||||
{this.props.items.map(function (item) {
|
||||
var href = '';
|
||||
switch (item.type) {
|
||||
|
|
|
@ -317,7 +317,7 @@ var Navigation = React.createClass({
|
|||
</ul>
|
||||
<Modal isOpen={this.state.canceledDeletionOpen}
|
||||
onRequestClose={this.closeCanceledDeletion}
|
||||
frameSettings={{padding: 15}}>
|
||||
style={{content:{padding: 15}}}>
|
||||
<h4>Your Account Will Not Be Deleted</h4>
|
||||
<p>
|
||||
Your account was scheduled for deletion but you logged in. Your account has been reactivated.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
var render = require('../../lib/render.jsx');
|
||||
|
||||
|
@ -20,9 +21,13 @@ var Hoc = React.createClass({
|
|||
});
|
||||
},
|
||||
render: function () {
|
||||
var classes = classNames(
|
||||
'top-banner',
|
||||
this.state.bgClass
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<div className={'top-banner ' + this.state.bgClass}>
|
||||
<div className={classes}>
|
||||
<h1>Get Creative with Coding</h1>
|
||||
<p>
|
||||
With Scratch, you can program your own stories, games, and animations —
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var injectIntl = require('react-intl').injectIntl;
|
||||
var omit = require('lodash.omit');
|
||||
var React = require('react');
|
||||
var render = require('../../lib/render.jsx');
|
||||
|
||||
|
@ -7,10 +8,12 @@ var Session = require('../../mixins/session.jsx');
|
|||
|
||||
var Activity = require('../../components/activity/activity.jsx');
|
||||
var AdminPanel = require('../../components/adminpanel/adminpanel.jsx');
|
||||
var Banner = require('../../components/banner/banner.jsx');
|
||||
var Box = require('../../components/box/box.jsx');
|
||||
var Button = require('../../components/forms/button.jsx');
|
||||
var Carousel = require('../../components/carousel/carousel.jsx');
|
||||
var Intro = require('../../components/intro/intro.jsx');
|
||||
var Modal = require('../../components/modal/modal.jsx');
|
||||
var News = require('../../components/news/news.jsx');
|
||||
var Welcome = require('../../components/welcome/welcome.jsx');
|
||||
|
||||
|
@ -28,7 +31,8 @@ var Splash = injectIntl(React.createClass({
|
|||
activity: [],
|
||||
news: [],
|
||||
featuredCustom: {},
|
||||
featuredGlobal: {}
|
||||
featuredGlobal: {},
|
||||
showEmailConfirmationModal: false
|
||||
};
|
||||
},
|
||||
componentDidUpdate: function (prevProps, prevState) {
|
||||
|
@ -43,6 +47,11 @@ var Splash = injectIntl(React.createClass({
|
|||
this.setState({news: []});
|
||||
this.getProjectCount();
|
||||
}
|
||||
if (this.shouldShowEmailConfirmation()) {
|
||||
window.addEventListener('message', this.onMessage);
|
||||
} else {
|
||||
window.removeEventListener('message', this.onMessage);
|
||||
}
|
||||
}
|
||||
},
|
||||
componentDidMount: function () {
|
||||
|
@ -54,6 +63,22 @@ var Splash = injectIntl(React.createClass({
|
|||
} else {
|
||||
this.getProjectCount();
|
||||
}
|
||||
if (this.shouldShowEmailConfirmation()) window.addEventListener('message', this.onMessage);
|
||||
},
|
||||
componentWillUnmount: function () {
|
||||
window.removeEventListener('message', this.onMessage);
|
||||
},
|
||||
onMessage: function (e) {
|
||||
if (e.origin != window.location.origin) return;
|
||||
if (e.source != this.refs.emailConfirmationiFrame.contentWindow) return;
|
||||
if (e.data == 'resend-done') {
|
||||
this.hideEmailConfirmationModal();
|
||||
} else {
|
||||
var data = JSON.parse(e.data);
|
||||
if (data['action'] === 'leave-page') {
|
||||
window.location.href = data['uri'];
|
||||
}
|
||||
}
|
||||
},
|
||||
getActivity: function () {
|
||||
this.api({
|
||||
|
@ -90,6 +115,12 @@ var Splash = injectIntl(React.createClass({
|
|||
if (!err) this.setState({projectCount: body.count});
|
||||
}.bind(this));
|
||||
},
|
||||
showEmailConfirmationModal: function () {
|
||||
this.setState({emailConfirmationModalOpen: true});
|
||||
},
|
||||
hideEmailConfirmationModal: function () {
|
||||
this.setState({emailConfirmationModalOpen: false});
|
||||
},
|
||||
handleDismiss: function (cue) {
|
||||
this.api({
|
||||
host: '',
|
||||
|
@ -108,6 +139,11 @@ var Splash = injectIntl(React.createClass({
|
|||
new Date(new Date - 2*7*24*60*60*1000) // Two weeks ago
|
||||
);
|
||||
},
|
||||
shouldShowEmailConfirmation: function () {
|
||||
return (
|
||||
this.state.session.user && this.state.session.flags.has_outstanding_email_confirmation &&
|
||||
this.state.session.flags.confirm_email_banner);
|
||||
},
|
||||
renderHomepageRows: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
|
||||
|
@ -249,58 +285,78 @@ var Splash = injectIntl(React.createClass({
|
|||
},
|
||||
render: function () {
|
||||
var featured = this.renderHomepageRows();
|
||||
var emailConfirmationStyle = {width: 500, height: 330, padding: 1};
|
||||
return (
|
||||
<div className="inner">
|
||||
{this.state.session.user ? [
|
||||
<div key="header" className="splash-header">
|
||||
{this.shouldShowWelcome() ? [
|
||||
<Welcome key="welcome" onDismiss={this.handleDismiss.bind(this, 'welcome')}/>
|
||||
] : [
|
||||
<Activity key="activity" items={this.state.activity} />
|
||||
]}
|
||||
<News items={this.state.news} />
|
||||
</div>
|
||||
] : [
|
||||
<Intro projectCount={this.state.projectCount} key="intro"/>
|
||||
]}
|
||||
<div className="splash">
|
||||
{this.shouldShowEmailConfirmation() ? [
|
||||
<Banner key="confirmedEmail"
|
||||
className="warning"
|
||||
onRequestDismiss={this.handleDismiss.bind(this, 'confirmed_email')}>
|
||||
<a href="#" onClick={this.showEmailConfirmationModal}>Confirm your email</a>
|
||||
{' '}to enable sharing.{' '}
|
||||
<a href="/info/faq/#accounts">Having trouble?</a>
|
||||
</Banner>,
|
||||
<Modal key="emailConfirmationModal"
|
||||
isOpen={this.state.emailConfirmationModalOpen}
|
||||
onRequestClose={this.hideEmailConfirmationModal}
|
||||
style={{content: emailConfirmationStyle}}>
|
||||
<iframe ref="emailConfirmationiFrame"
|
||||
src="/accounts/email_resend_standalone/"
|
||||
{...omit(emailConfirmationStyle, 'padding')} />
|
||||
</Modal>
|
||||
] : []}
|
||||
<div key="inner" className="inner">
|
||||
{this.state.session.user ? [
|
||||
<div key="header" className="splash-header">
|
||||
{this.state.session.flags.show_welcome ? [
|
||||
<Welcome key="welcome" onDismiss={this.handleDismiss.bind(this, 'welcome')}/>
|
||||
] : [
|
||||
<Activity key="activity" items={this.state.activity} />
|
||||
]}
|
||||
<News items={this.state.news} />
|
||||
</div>
|
||||
] : [
|
||||
<Intro projectCount={this.state.projectCount} key="intro"/>
|
||||
]}
|
||||
|
||||
{featured}
|
||||
{featured}
|
||||
|
||||
<AdminPanel>
|
||||
<dt>Tools</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/scratch_admin/tickets">Ticket Queue</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/scratch_admin/ip-search/">IP Search</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/scratch_admin/email-search/">Email Search</a>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>Homepage Cache</dt>
|
||||
<dd>
|
||||
<ul className="cache-list">
|
||||
<li>
|
||||
<form
|
||||
id="homepage-refresh-form"
|
||||
method="post"
|
||||
action="/scratch_admin/homepage/clear-cache/">
|
||||
|
||||
<div className="button-row">
|
||||
<span>Refresh row data:</span>
|
||||
<Button type="submit">
|
||||
<span>Refresh</span>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</AdminPanel>
|
||||
<AdminPanel>
|
||||
<dt>Tools</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/scratch_admin/tickets">Ticket Queue</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/scratch_admin/ip-search/">IP Search</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/scratch_admin/email-search/">Email Search</a>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt>Homepage Cache</dt>
|
||||
<dd>
|
||||
<ul className="cache-list">
|
||||
<li>
|
||||
<form
|
||||
id="homepage-refresh-form"
|
||||
method="post"
|
||||
action="/scratch_admin/homepage/clear-cache/">
|
||||
|
||||
<div className="button-row">
|
||||
<span>Refresh row data:</span>
|
||||
<Button type="submit">
|
||||
<span>Refresh</span>
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</AdminPanel>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue