feat(splash): add privacy banner (first draft)

This commit is contained in:
cori hudson 2023-04-19 11:51:35 -04:00
parent 0c7bacf77f
commit d8192e669f
4 changed files with 106 additions and 1 deletions

View file

@ -35,6 +35,7 @@ const ShareProjectMessage = require('./activity-rows/share-project.jsx');
const DonateBanner = require('./donate/donate-banner.jsx'); const DonateBanner = require('./donate/donate-banner.jsx');
const HOCTopBanner = require('./hoc/top-banner.jsx'); const HOCTopBanner = require('./hoc/top-banner.jsx');
const HOCMiddleBanner = require('./hoc/middle-banner.jsx'); const HOCMiddleBanner = require('./hoc/middle-banner.jsx');
const PrivacyBanner = require('./privacy/privacy-banner.jsx');
require('./splash.scss'); require('./splash.scss');
@ -384,6 +385,13 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
</MediaQuery> </MediaQuery>
) )
} }
{
this.props.shouldShowPrivacyBanner && (
<PrivacyBanner
onRequestClose={this.props.onClosePrivacyBanner}
/>
)
}
{ {
this.props.shouldShowIntro && ( this.props.shouldShowIntro && (
<Intro <Intro
@ -533,6 +541,7 @@ SplashPresentation.propTypes = {
news: PropTypes.arrayOf(PropTypes.object), news: PropTypes.arrayOf(PropTypes.object),
onCloseAdminPanel: PropTypes.func.isRequired, onCloseAdminPanel: PropTypes.func.isRequired,
onCloseDonateBanner: PropTypes.func.isRequired, onCloseDonateBanner: PropTypes.func.isRequired,
onClosePrivacyBanner: PropTypes.func.isRequired,
onDismiss: PropTypes.func.isRequired, onDismiss: PropTypes.func.isRequired,
onOpenAdminPanel: PropTypes.func.isRequired, onOpenAdminPanel: PropTypes.func.isRequired,
onRefreshHomepageCache: PropTypes.func.isRequired, onRefreshHomepageCache: PropTypes.func.isRequired,
@ -545,6 +554,7 @@ SplashPresentation.propTypes = {
shouldShowIntro: PropTypes.bool.isRequired, shouldShowIntro: PropTypes.bool.isRequired,
shouldShowHOCMiddleBanner: PropTypes.bool.isRequired, shouldShowHOCMiddleBanner: PropTypes.bool.isRequired,
shouldShowWelcome: PropTypes.bool.isRequired, shouldShowWelcome: PropTypes.bool.isRequired,
shouldShowPrivacyBanner: PropTypes.bool.isRequired,
user: PropTypes.object.isRequired // eslint-disable-line react/forbid-prop-types user: PropTypes.object.isRequired // eslint-disable-line react/forbid-prop-types
}; };

View file

@ -0,0 +1,40 @@
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('./privacy-banner.scss');
const PrivacyBanner = ({
onRequestClose
}) => (
<TitleBanner className="privacy-banner">
<div className="privacy-banner-container">
<p className="privacy-banner-text">
The Scratch privacy policy has been updated, effective xx yy, 2023.
You can see the new policy <a href="/privacy_policy">here</a>.
</p>
<Button
isCloseType
className="privacy-close-button"
key="closeButton"
name="closeButton"
type="button"
onClick={onRequestClose}
>
<div className="action-button-text">
<FormattedMessage id="general.close" />
</div>
</Button>
</div>
</TitleBanner>
);
PrivacyBanner.propTypes = {
onRequestClose: PropTypes.func
};
module.exports = injectIntl(PrivacyBanner);

View file

@ -0,0 +1,34 @@
@import '../../../colors';
.privacy-banner {
display: flex;
position: sticky;
z-index: 8;
background-color: $ui-blue;
overflow: hidden;
align-items: center;
justify-content: center;
margin-bottom: 0px;
padding: 8px 0;
.privacy-banner-container {
display: flex;
align-items: center;
}
.privacy-close-button {
right: 1rem;
top: auto;
}
.privacy-banner-text {
color: $ui-white;
font-size: 1rem;
font-weight: bold;
}
a {
color: $ui-white;
text-decoration: underline;
}
}

View file

@ -8,6 +8,7 @@ const log = require('../../lib/log');
const render = require('../../lib/render.jsx'); const render = require('../../lib/render.jsx');
const sessionActions = require('../../redux/session.js'); const sessionActions = require('../../redux/session.js');
const splashActions = require('../../redux/splash.js'); const splashActions = require('../../redux/splash.js');
const jar = require('../../lib/jar.js');
const Page = require('../../components/page/www/page.jsx'); const Page = require('../../components/page/www/page.jsx');
const SplashPresentation = require('./presentation.jsx'); const SplashPresentation = require('./presentation.jsx');
@ -19,6 +20,9 @@ const SCRATCH_WEEK_START_TIME = 1621224000000; // 2021-05-17 00:00:00 -- No end
const HOC_START_TIME = 1668574800000; // 2022-11-16 00:00:00 GMT in ms const HOC_START_TIME = 1668574800000; // 2022-11-16 00:00:00 GMT in ms
const HOC_END_TIME = 1670821200000; // 2022-12-12 00:00:00 GMT in ms const HOC_END_TIME = 1670821200000; // 2022-12-12 00:00:00 GMT in ms
const PRIVACY_UPDATE_START_TIME = 1681826142976; // TODO: coordinate this later
const PRIVACY_UPDATE_END_TIME = 1713434255000; // TODO: see above
class Splash extends React.Component { class Splash extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
@ -28,10 +32,12 @@ class Splash extends React.Component {
'getHomepageRefreshStatus', 'getHomepageRefreshStatus',
'handleCloseAdminPanel', 'handleCloseAdminPanel',
'handleCloseDonateBanner', 'handleCloseDonateBanner',
'handleClosePrivacyBanner',
'handleOpenAdminPanel', 'handleOpenAdminPanel',
'handleDismiss', 'handleDismiss',
'shouldShowWelcome', 'shouldShowWelcome',
'shouldShowEmailConfirmation' 'shouldShowEmailConfirmation',
'shouldShowPrivacyBanner'
]); ]);
this.state = { this.state = {
adminPanelOpen: false, adminPanelOpen: false,
@ -123,6 +129,11 @@ class Splash extends React.Component {
handleCloseDonateBanner () { handleCloseDonateBanner () {
this.setState({dismissedDonateBanner: true}); this.setState({dismissedDonateBanner: true});
} }
handleClosePrivacyBanner () {
const opts = {};
this.setState({dismissedPrivacyBanner: true});
jar.set('scratchpolicyseen', true, opts);
}
handleDismiss (cue) { handleDismiss (cue) {
api({ api({
host: '', host: '',
@ -173,11 +184,19 @@ class Splash extends React.Component {
Date.now() >= SCRATCH_WEEK_START_TIME Date.now() >= SCRATCH_WEEK_START_TIME
); );
} }
shouldShowPrivacyBanner () {
const seen = jar.get('scratchpolicyseen');
if (typeof seen === 'undefined') {
return Date.now() >= PRIVACY_UPDATE_START_TIME && Date.now() < PRIVACY_UPDATE_END_TIME;
}
return false;
}
render () { render () {
const showEmailConfirmation = this.shouldShowEmailConfirmation() || false; const showEmailConfirmation = this.shouldShowEmailConfirmation() || false;
const showDonateBanner = this.shouldShowDonateBanner() || false; const showDonateBanner = this.shouldShowDonateBanner() || false;
const showHOCTopBanner = this.shouldShowHOCTopBanner() || false; const showHOCTopBanner = this.shouldShowHOCTopBanner() || false;
const showHOCMiddleBanner = this.shouldShowHOCMiddleBanner() || false; const showHOCMiddleBanner = this.shouldShowHOCMiddleBanner() || false;
const showPrivacyBanner = this.shouldShowPrivacyBanner() || false;
const showIntro = this.shouldShowIntro() || false; const showIntro = this.shouldShowIntro() || false;
const showWelcome = this.shouldShowWelcome(); const showWelcome = this.shouldShowWelcome();
const homepageRefreshStatus = this.getHomepageRefreshStatus(); const homepageRefreshStatus = this.getHomepageRefreshStatus();
@ -200,10 +219,12 @@ class Splash extends React.Component {
shouldShowHOCTopBanner={showHOCTopBanner} shouldShowHOCTopBanner={showHOCTopBanner}
shouldShowIntro={showIntro} shouldShowIntro={showIntro}
shouldShowHOCMiddleBanner={showHOCMiddleBanner} shouldShowHOCMiddleBanner={showHOCMiddleBanner}
shouldShowPrivacyBanner={showPrivacyBanner}
shouldShowWelcome={showWelcome} shouldShowWelcome={showWelcome}
user={this.props.user} user={this.props.user}
onCloseDonateBanner={this.handleCloseDonateBanner} onCloseDonateBanner={this.handleCloseDonateBanner}
onCloseAdminPanel={this.handleCloseAdminPanel} onCloseAdminPanel={this.handleCloseAdminPanel}
onClosePrivacyBanner={this.handleClosePrivacyBanner}
onDismiss={this.handleDismiss} onDismiss={this.handleDismiss}
onOpenAdminPanel={this.handleOpenAdminPanel} onOpenAdminPanel={this.handleOpenAdminPanel}
onRefreshHomepageCache={this.handleRefreshHomepageCache} onRefreshHomepageCache={this.handleRefreshHomepageCache}