Unverified Commit 4591c65e authored by Benjamin Wheeler's avatar Benjamin Wheeler Committed by GitHub

Merge pull request #5345 from benjiwheeler/donate-banner

add donate banner, make close button a mode of button component
parents 7876bc4f 3dd69c28
......@@ -26,6 +26,7 @@ $background-color: hsla(0, 0, 99, 1); //#FDFDFD
/* 3.0 colors */
/* Using www naming convention for now, should be consistent with gui */
$ui-aqua: hsla(163, 85, 40, 1); // #0FBD8C Extension Primary
$ui-aqua-dark: hsla(163, 85, 30, 1); // #0B8E69 Extension Aqua 3
$ui-purple: hsla(260, 100, 70, 1); // #9966FF Looks Primary
$ui-purple-dark: hsla(260, 60, 60, 1); // #774DCB Looks Secondary
$ui-magenta: hsla(300, 53%, 60%, 1); /* #CF63CF Sounds Primary */
......
......@@ -6,21 +6,38 @@ const React = require('react');
require('./button.scss');
const Button = props => {
const classes = classNames('button', props.className);
const classes = classNames('button', props.className, {'close-button': props.isCloseType});
return (
<button
className={classes}
{...omit(props, ['className', 'children'])}
{...omit(props, ['className', 'children', 'isCloseType'])}
>
{props.children}
{
props.isCloseType ? (
<img
alt="close-icon"
className="modal-content-close-img"
draggable="false"
src="/svgs/modal/close-x.svg"
/>
) : [
props.children
]
}
</button>
);
};
Button.propTypes = {
children: PropTypes.node,
className: PropTypes.string
className: PropTypes.string,
isCloseType: PropTypes.bool
};
Button.defaultProps = {
className: '',
isCloseType: false
};
module.exports = Button;
......@@ -53,3 +53,22 @@ $pass-bg: $ui-aqua;
margin-right: -.25rem;
}
}
.close-button {
padding: 0;
position: absolute;
top: 0.5rem;
right: 0.5rem;
border-radius: 1rem;
background-color: $active-gray;
cursor: pointer;
width: 2rem;
height: 2rem;
text-align: center;
line-height: 2rem;
}
.close-button img {
padding-top: 0.5rem;
}
const FormattedMessage = require('react-intl').FormattedMessage;
const injectIntl = require('react-intl').injectIntl;
const PropTypes = require('prop-types');
const React = require('react');
const TitleBanner = require('../../../components/title-banner/title-banner.jsx');
const Button = require('../../../components/forms/button.jsx');
require('./donate-banner.scss');
const navigateToDonatePage = () => {
window.location = 'https://secure.donationpay.org/scratchfoundation';
};
const DonateTopBanner = ({
onRequestClose
}) => (
<TitleBanner className="donate-banner">
<div className="donate-container">
<img
className="donate-icon"
src="/images/ideas/try-it-icon.svg"
/>
<div className="donate-central-items">
<p className="donate-text">
<FormattedMessage id="donatebanner.askSupport" />
</p>
<Button
className="donate-button"
key="add-to-studio-button"
onClick={navigateToDonatePage}
>
<FormattedMessage id="general.donate" />
</Button>
</div>
</div>
<Button
isCloseType
className="donate-close-button"
key="closeButton"
name="closeButton"
type="button"
onClick={onRequestClose}
>
<div className="action-button-text">
<FormattedMessage id="general.close" />
</div>
</Button>
</TitleBanner>
);
DonateTopBanner.propTypes = {
onRequestClose: PropTypes.func
};
module.exports = injectIntl(DonateTopBanner);
@import "../../../colors";
@import "../../../frameless";
$tile-height: 244px;
.donate-banner {
display: flex;
position: fixed;
z-index: 8;
background-color: $ui-aqua-dark;
padding: 0;
overflow: hidden;
align-items: center;
justify-content: center;
.donate-container {
display: flex;
margin: 0.375rem auto;
align-items: center;
.donate-icon {
margin: 0.6875rem;
width: 1.75rem;
height: 1.75rem;
}
.donate-central-items {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
}
.donate-text {
text-align: left;
color: $ui-white;
font-size: 1rem;
font-weight: bold;
margin-right: 1rem;
max-width: 70vw;
}
.donate-button {
margin: 0 7rem 0 .5rem;
border-radius: 1.25rem;
background-color: $ui-white;
color: $ui-aqua-dark;
padding: 0 1.75rem;
height: 2.25rem;
text-decoration: none;
line-height: .875rem;
font-size: 1rem;
font-weight: bold;
}
}
.donate-close-button {
right: 1rem;
top: auto;
}
}
@media only screen and (max-width: $mobileIntermediate) {
.donate-banner .donate-container .donate-central-items {
flex-wrap: wrap;
}
.donate-banner .donate-container .donate-icon {
padding-bottom: 2rem;
}
.donate-banner .donate-container .donate-button {
margin-left: 0;
margin-bottom: 1rem
}
.donate-banner .donate-close-button {
top: 1rem;
}
}
......@@ -29,6 +29,8 @@
"intro.watchVideo": "Watch Video",
"news.scratchNews": "Scratch News",
"donatebanner.askSupport": "Scratch is the world's largest free coding community for kids. Your support makes a difference.",
"teacherbanner.greeting": "Hi",
"teacherbanner.subgreeting": "Teacher Account",
"teacherbanner.classesButton": "My Classes",
......
......@@ -32,12 +32,10 @@ const LoveProjectMessage = require('./activity-rows/love-project.jsx');
const RemixProjectMessage = require('./activity-rows/remix-project.jsx');
const ShareProjectMessage = require('./activity-rows/share-project.jsx');
// Hour of Code Banner Components
const TopBanner = require('./hoc/top-banner.jsx');
const MiddleBanner = require('./hoc/middle-banner.jsx');
const HOC_START_TIME = 1605484800000; // 2020-11-16 00:00:00
const HOC_END_TIME = 1608681600000; // 2020-12-23 00:00:00
// Banner Components
const DonateBanner = require('./donate/donate-banner.jsx');
const HOCTopBanner = require('./hoc/top-banner.jsx');
const HOCMiddleBanner = require('./hoc/middle-banner.jsx');
require('./splash.scss');
......@@ -352,6 +350,7 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
const formatHTMLMessage = this.props.intl.formatHTMLMessage;
const formatMessage = this.props.intl.formatMessage;
const messages = {
'general.viewAll': formatMessage({id: 'general.viewAll'}),
'news.scratchNews': formatMessage({id: 'news.scratchNews'}),
......@@ -412,21 +411,28 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
/>
] : []}
{
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length === 0 && (// Only show top banner if user is not logged in
(Date.now() >= HOC_START_TIME && Date.now() < HOC_END_TIME) ? (
<MediaQuery
key="frameless-tablet"
minWidth={frameless.tabletPortrait}
>
<TopBanner />
</MediaQuery>
) : (
<Intro
key="intro"
messages={messages}
/>
)
this.props.shouldShowHOCTopBanner && (
<MediaQuery
key="frameless-tablet"
minWidth={frameless.tabletPortrait}
>
<HOCTopBanner />
</MediaQuery>
)
}
{
this.props.shouldShowDonateBanner && (
<DonateBanner
onRequestClose={this.props.onCloseDonateBanner}
/>
)
}
{
this.props.shouldShowIntro && (
<Intro
key="intro"
messages={messages}
/>
)
}
<div
......@@ -464,17 +470,14 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
{featured.shift()}
</div>
{
this.props.sessionStatus === sessionActions.Status.FETCHED &&
Object.keys(this.props.user).length !== 0 && // Only show if user is logged in
Date.now() >= HOC_START_TIME && // Show middle banner on and after Dec 3
Date.now() < HOC_END_TIME && // Hide middle banner after Dec 14
false && // we did not use this middle banner in last HoC
<MediaQuery
key="frameless-desktop"
minWidth={frameless.tabletPortrait}
>
<MiddleBanner />
</MediaQuery>
this.props.shouldShowHOCMiddleBanner && (
<MediaQuery
key="frameless-desktop"
minWidth={frameless.tabletPortrait}
>
<HOCMiddleBanner />
</MediaQuery>
)
}
<div
......@@ -573,6 +576,7 @@ SplashPresentation.propTypes = {
lovedByFollowing: PropTypes.arrayOf(PropTypes.object),
news: PropTypes.arrayOf(PropTypes.object),
onCloseAdminPanel: PropTypes.func.isRequired,
onCloseDonateBanner: PropTypes.func.isRequired,
onDismiss: PropTypes.func.isRequired,
onHideEmailConfirmationModal: PropTypes.func.isRequired,
onOpenAdminPanel: PropTypes.func.isRequired,
......@@ -581,7 +585,11 @@ SplashPresentation.propTypes = {
refreshCacheStatus: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
sessionStatus: PropTypes.string.isRequired,
sharedByFollowing: PropTypes.arrayOf(PropTypes.object),
shouldShowDonateBanner: PropTypes.bool.isRequired,
shouldShowEmailConfirmation: PropTypes.bool.isRequired,
shouldShowHOCTopBanner: PropTypes.bool.isRequired,
shouldShowIntro: PropTypes.bool.isRequired,
shouldShowHOCMiddleBanner: PropTypes.bool.isRequired,
shouldShowWelcome: PropTypes.bool.isRequired,
user: PropTypes.object.isRequired // eslint-disable-line react/forbid-prop-types
};
......
......@@ -12,6 +12,11 @@ const splashActions = require('../../redux/splash.js');
const Page = require('../../components/page/www/page.jsx');
const SplashPresentation = require('./presentation.jsx');
const SCRATCH_WEEK_START_TIME = 1621224000000; // 2021-05-17 00:00:00
const SCRATCH_WEEK_END_TIME = 1621828800000; // 2021-05-24 00:00:00
const HOC_START_TIME = 1605484800000; // 2020-11-16 00:00:00
const HOC_END_TIME = 1608681600000; // 2020-12-23 00:00:00
class Splash extends React.Component {
constructor (props) {
super(props);
......@@ -22,6 +27,7 @@ class Splash extends React.Component {
'handleShowEmailConfirmationModal',
'handleHideEmailConfirmationModal',
'handleCloseAdminPanel',
'handleCloseDonateBanner',
'handleOpenAdminPanel',
'handleDismiss',
'shouldShowWelcome',
......@@ -29,8 +35,9 @@ class Splash extends React.Component {
]);
this.state = {
adminPanelOpen: false,
dismissedDonateBanner: false,
news: [], // gets news posts from the scratch Tumblr
emailConfirmationModalOpen: false, // flag that determines whether to show banner to request email conf.
emailConfirmationModalOpen: false,
refreshCacheStatus: 'notrequested'
};
}
......@@ -114,6 +121,9 @@ class Splash extends React.Component {
handleOpenAdminPanel () {
this.setState({adminPanelOpen: true});
}
handleCloseDonateBanner () {
this.setState({dismissedDonateBanner: true});
}
handleShowEmailConfirmationModal () {
this.setState({emailConfirmationModalOpen: true});
}
......@@ -144,8 +154,33 @@ class Splash extends React.Component {
this.props.flags.confirm_email_banner
);
}
shouldShowHOCTopBanner () {
return (
this.props.sessionStatus === sessionActions.Status.FETCHED && // done fetching session
Object.keys(this.props.user).length === 0 && // no user session found
Date.now() >= HOC_START_TIME &&
Date.now() < HOC_END_TIME
);
}
shouldShowHOCMiddleBanner () {
return false; // we did not use this middle banner in last HoC
}
shouldShowDonateBanner () {
return (
this.state.dismissedDonateBanner === false &&
this.props.sessionStatus === sessionActions.Status.FETCHED && // done fetching session
Object.keys(this.props.user).length === 0 && // no user session found
Date.now() >= SCRATCH_WEEK_START_TIME &&
Date.now() < SCRATCH_WEEK_END_TIME &&
this.shouldShowHOCTopBanner() !== true
);
}
render () {
const showEmailConfirmation = this.shouldShowEmailConfirmation() || false;
const showDonateBanner = this.shouldShowDonateBanner() || false;
const showHOCTopBanner = this.shouldShowHOCTopBanner() || false;
const showHOCMiddleBanner = this.shouldShowHOCMiddleBanner() || false;
const showIntro = showHOCTopBanner !== true;
const showWelcome = this.shouldShowWelcome();
const homepageRefreshStatus = this.getHomepageRefreshStatus();
......@@ -163,9 +198,14 @@ class Splash extends React.Component {
refreshCacheStatus={homepageRefreshStatus}
sessionStatus={this.props.sessionStatus}
sharedByFollowing={this.props.shared}
shouldShowDonateBanner={showDonateBanner}
shouldShowEmailConfirmation={showEmailConfirmation}
shouldShowHOCTopBanner={showHOCTopBanner}
shouldShowIntro={showIntro}
shouldShowHOCMiddleBanner={showHOCMiddleBanner}
shouldShowWelcome={showWelcome}
user={this.props.user}
onCloseDonateBanner={this.handleCloseDonateBanner}
onCloseAdminPanel={this.handleCloseAdminPanel}
onDismiss={this.handleDismiss}
onHideEmailConfirmationModal={this.handleHideEmailConfirmationModal}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment