Unverified Commit af32c089 authored by Ray Schamp's avatar Ray Schamp Committed by GitHub

Merge pull request #2413 from rschamp/mod-panel-phase-3

Match scratchr2 admin panel behavior more closely
parents 7ac90afb 15cc6ca5
const bindAll = require('lodash.bindall');
const classNames = require('classnames');
const connect = require('react-redux').connect;
const PropTypes = require('prop-types');
const React = require('react');
require('./adminpanel.scss');
class AdminPanel extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleToggleVisibility'
]);
this.state = {
showPanel: false
};
}
handleToggleVisibility (e) {
e.preventDefault();
this.setState({showPanel: !this.state.showPanel});
}
render () {
if (!this.props.isAdmin) return false;
return (
<div
className={classNames(
'admin-panel', this.props.className, {
hidden: !this.state.showPanel
}
)}
const AdminPanel = ({
className,
children,
isOpen,
onOpen,
onClose
}) => (
<div className={classNames('admin-panel', className, {hidden: !isOpen})}>
{isOpen ? (
<React.Fragment>
<span
className="toggle"
onClick={onClose}
>
x
</span>
<div className="admin-header">
<h3>Admin Panel</h3>
</div>
<div className="admin-content">
{children}
</div>
</React.Fragment>
) : (
<span
className="toggle"
onClick={onOpen}
>
{this.state.showPanel ? (
<React.Fragment>
<span
className="toggle"
onClick={this.handleToggleVisibility}
>
x
</span>
<div className="admin-header">
<h3>Admin Panel</h3>
</div>
<div className="admin-content">
{this.props.children}
</div>
</React.Fragment>
) : (
<span
className="toggle"
onClick={this.handleToggleVisibility}
>
&gt;
</span>
)}
</div>
);
}
}
&gt;
</span>
)}
</div>
);
AdminPanel.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
isAdmin: PropTypes.bool
isOpen: PropTypes.bool,
onClose: PropTypes.func,
onOpen: PropTypes.func
};
const mapStateToProps = state => ({
isAdmin: state.permissions.admin
});
const ConnectedAdminPanel = connect(mapStateToProps)(AdminPanel);
module.exports = ConnectedAdminPanel;
module.exports = AdminPanel;
......@@ -47,6 +47,7 @@ const onKeyPress = e => {
const PreviewPresentation = ({
addToStudioOpen,
adminModalOpen,
adminPanelOpen,
assetHost,
backpackHost,
canAddToStudio,
......@@ -77,11 +78,13 @@ const PreviewPresentation = ({
onAddComment,
onAddToStudioClicked,
onAddToStudioClosed,
onCloseAdminPanel,
onCopyProjectLink,
onDeleteComment,
onFavoriteClicked,
onLoadMore,
onLoveClicked,
onOpenAdminPanel,
onRemix,
onReportClicked,
onReportClose,
......@@ -164,8 +167,12 @@ const PreviewPresentation = ({
<div className="preview">
<AdminPanel
className={classNames('project-admin-panel', {
'admin-panel-open': adminPanelOpen,
'modal-open': adminModalOpen
})}
isOpen={adminPanelOpen}
onClose={onCloseAdminPanel}
onOpen={onOpenAdminPanel}
>
<iframe
className={classNames('admin-iframe', {
......@@ -545,6 +552,7 @@ const PreviewPresentation = ({
PreviewPresentation.propTypes = {
addToStudioOpen: PropTypes.bool,
adminModalOpen: PropTypes.bool,
adminPanelOpen: PropTypes.bool,
assetHost: PropTypes.string,
backpackHost: PropTypes.string,
canAddToStudio: PropTypes.bool,
......@@ -578,11 +586,13 @@ PreviewPresentation.propTypes = {
onAddComment: PropTypes.func,
onAddToStudioClicked: PropTypes.func,
onAddToStudioClosed: PropTypes.func,
onCloseAdminPanel: PropTypes.func,
onCopyProjectLink: PropTypes.func,
onDeleteComment: PropTypes.func,
onFavoriteClicked: PropTypes.func,
onLoadMore: PropTypes.func,
onLoveClicked: PropTypes.func,
onOpenAdminPanel: PropTypes.func,
onRemix: PropTypes.func,
onReportClicked: PropTypes.func.isRequired,
onReportClose: PropTypes.func.isRequired,
......
......@@ -35,17 +35,30 @@ $stage-width: 480px;
}
}
.project-admin-panel {
border: 0;
padding: 1rem;
overflow: hidden;
}
.project-admin-panel.admin-panel-open {
padding: 0;
width: 237px;
}
.admin-iframe {
position: absolute;
top: 0;
left: 0;
z-index: 100;
width: 252px;
margin: 0;
border: 0;
width: 237px;
height: 100%;
}
.admin-iframe.modal-open,
.project-admin-panel.modal-open {
.project-admin-panel.admin-panel-open.modal-open {
background-color: transparent;
width: 100%;
}
......
......@@ -32,6 +32,8 @@ const frameless = require('../../lib/frameless');
const GUI = require('scratch-gui');
const IntlGUI = injectIntl(GUI.default);
const localStorageAvailable = 'localStorage' in window && window.localStorage !== null;
class Preview extends React.Component {
constructor (props) {
super(props);
......@@ -47,6 +49,8 @@ class Preview extends React.Component {
'handleLoveToggle',
'handleMessage',
'handlePopState',
'handleCloseAdminPanel',
'handleOpenAdminPanel',
'handleReportClick',
'handleReportClose',
'handleReportComment',
......@@ -78,9 +82,12 @@ class Preview extends React.Component {
const singleCommentId = window.location.hash.indexOf(commentHashPrefix) !== -1 &&
parseInt(window.location.hash.replace(commentHashPrefix, ''), 10);
const adminPanelOpen = localStorageAvailable && localStorage.getItem('adminPanelToggled_projects') === 'open';
this.state = {
addToStudioOpen: false,
adminModalOpen: false,
adminPanelOpen: adminPanelOpen || false,
extensions: [],
favoriteCount: 0,
invalidProject: parts.length === 1,
......@@ -264,6 +271,18 @@ class Preview extends React.Component {
handleDeleteComment (id, topLevelCommentId) {
this.props.handleDeleteComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
}
handleCloseAdminPanel () {
this.setState({adminPanelOpen: false});
if (localStorageAvailable) {
localStorage.setItem('adminPanelToggled_projects', 'closed');
}
}
handleOpenAdminPanel () {
this.setState({adminPanelOpen: true});
if (localStorageAvailable) {
localStorage.setItem('adminPanelToggled_projects', 'open');
}
}
handleMessage (messageEvent) {
if (messageEvent.data === 'showDialog') {
this.setState({
......@@ -275,6 +294,8 @@ class Preview extends React.Component {
adminModalOpen: false
});
}
if (messageEvent.data === 'openPanel') this.handleOpenAdminPanel();
if (messageEvent.data === 'closePanel') this.handleCloseAdminPanel();
}
handleReportComment (id, topLevelCommentId) {
this.props.handleReportComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
......@@ -483,6 +504,7 @@ class Preview extends React.Component {
<PreviewPresentation
addToStudioOpen={this.state.addToStudioOpen}
adminModalOpen={this.state.adminModalOpen}
adminPanelOpen={this.state.adminPanelOpen}
assetHost={this.props.assetHost}
backpackHost={this.props.backpackHost}
canAddToStudio={this.props.canAddToStudio}
......@@ -525,11 +547,13 @@ class Preview extends React.Component {
onAddComment={this.handleAddComment}
onAddToStudioClicked={this.handleAddToStudioClick}
onAddToStudioClosed={this.handleAddToStudioClose}
onCloseAdminPanel={this.handleCloseAdminPanel}
onCopyProjectLink={this.handleCopyProjectLink}
onDeleteComment={this.handleDeleteComment}
onFavoriteClicked={this.handleFavoriteToggle}
onLoadMore={this.handleLoadMore}
onLoveClicked={this.handleLoveToggle}
onOpenAdminPanel={this.handleOpenAdminPanel}
onRemix={this.handleRemix}
onReportClicked={this.handleReportClick}
onReportClose={this.handleReportClose}
......
......@@ -530,7 +530,12 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
{featured}
{this.props.isAdmin && (
<AdminPanel className="splash-admin-panel">
<AdminPanel
className="splash-admin-panel"
isOpen={this.props.adminPanelOpen}
onClose={this.props.onCloseAdminPanel}
onOpen={this.props.onOpenAdminPanel}
>
<dl>
<dt>Tools</dt>
<dd>
......@@ -597,6 +602,7 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
SplashPresentation.propTypes = {
activity: PropTypes.arrayOf(PropTypes.object),
adminPanelOpen: PropTypes.bool,
emailConfirmationModalOpen: PropTypes.bool.isRequired,
featuredGlobal: PropTypes.shape({
community_featured_projects: PropTypes.array,
......@@ -612,8 +618,10 @@ SplashPresentation.propTypes = {
isEducator: PropTypes.bool.isRequired,
lovedByFollowing: PropTypes.arrayOf(PropTypes.object),
news: PropTypes.arrayOf(PropTypes.object),
onCloseAdminPanel: PropTypes.func.isRequired,
onDismiss: PropTypes.func.isRequired,
onHideEmailConfirmationModal: PropTypes.func.isRequired,
onOpenAdminPanel: PropTypes.func.isRequired,
onRefreshHomepageCache: PropTypes.func.isRequired,
onShowEmailConfirmationModal: PropTypes.func.isRequired,
projectCount: PropTypes.number,
......
......@@ -22,11 +22,14 @@ class Splash extends React.Component {
'getHomepageRefreshStatus',
'handleShowEmailConfirmationModal',
'handleHideEmailConfirmationModal',
'handleCloseAdminPanel',
'handleOpenAdminPanel',
'handleDismiss',
'shouldShowWelcome',
'shouldShowEmailConfirmation'
]);
this.state = {
adminPanelOpen: false,
projectCount: 30000000, // gets the shared project count
news: [], // gets news posts from the scratch Tumblr
emailConfirmationModalOpen: false, // flag that determines whether to show banner to request email conf.
......@@ -118,6 +121,12 @@ class Splash extends React.Component {
}
return status;
}
handleCloseAdminPanel () {
this.setState({adminPanelOpen: false});
}
handleOpenAdminPanel () {
this.setState({adminPanelOpen: true});
}
handleShowEmailConfirmationModal () {
this.setState({emailConfirmationModalOpen: true});
}
......@@ -156,6 +165,7 @@ class Splash extends React.Component {
return (
<SplashPresentation
activity={this.props.activity}
adminPanelOpen={this.state.adminPanelOpen}
emailConfirmationModalOpen={this.state.emailConfirmationModalOpen}
featuredGlobal={this.props.featured}
inStudiosFollowing={this.props.studios}
......@@ -170,8 +180,10 @@ class Splash extends React.Component {
shouldShowEmailConfirmation={showEmailConfirmation}
shouldShowWelcome={showWelcome}
user={this.props.user}
onCloseAdminPanel={this.handleCloseAdminPanel}
onDismiss={this.handleDismiss}
onHideEmailConfirmationModal={this.handleHideEmailConfirmationModal}
onOpenAdminPanel={this.handleOpenAdminPanel}
onRefreshHomepageCache={this.handleRefreshHomepageCache}
onShowEmailConfirmationModal={this.handleShowEmailConfirmationModal}
/>
......
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