Basic project admin panel support

Just in case we don't do anything else, this "proxies" the old admin panel to the new project page.

Requires https://github.com/LLK/scratchr2/pull/5219 to work.
This commit is contained in:
Ray Schamp 2018-12-05 15:40:18 -05:00
parent 4a57d36112
commit 726a2005bb
7 changed files with 164 additions and 123 deletions

View file

@ -1,10 +1,9 @@
const bindAll = require('lodash.bindall');
const classNames = require('classnames');
const connect = require('react-redux').connect;
const PropTypes = require('prop-types');
const React = require('react');
const Button = require('../forms/button.jsx');
require('./adminpanel.scss');
class AdminPanel extends React.Component {
@ -23,13 +22,16 @@ class AdminPanel extends React.Component {
}
render () {
if (!this.props.isAdmin) return false;
if (this.state.showPanel) {
return (
<div
className="visible"
id="admin-panel"
className={classNames(
'admin-panel', this.props.className, {
hidden: !this.state.showPanel
}
)}
>
{this.state.showPanel ? (
<React.Fragment>
<span
className="toggle"
onClick={this.handleToggleVisibility}
@ -40,47 +42,17 @@ class AdminPanel extends React.Component {
<h3>Admin Panel</h3>
</div>
<div className="admin-content">
<dl>
{this.props.children}
<dt>Page Cache</dt>
<dd>
<ul className="cache-list">
<li>
<form
action="/scratch_admin/page/clear-anon-cache/"
method="post"
>
<input
name="path"
type="hidden"
value="/"
/>
<div className="button-row">
<span>For anonymous users:</span>
<Button type="submit">
<span>Clear</span>
</Button>
</div>
</form>
</li>
</ul>
</dd>
</dl>
</div>
</div>
);
}
return (
<div
className="hidden"
id="admin-panel"
>
</React.Fragment>
) : (
<span
className="toggle"
onClick={this.handleToggleVisibility}
>
&gt;
</span>
)}
</div>
);
}
@ -88,6 +60,7 @@ class AdminPanel extends React.Component {
AdminPanel.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
isAdmin: PropTypes.bool
};

View file

@ -1,6 +1,6 @@
@import "../../colors";
#admin-panel {
.admin-panel {
position: fixed;
top: 0;
left: 0;
@ -8,17 +8,12 @@
border: 1px solid $ui-gray;
box-shadow: 0 2px 5px $box-shadow-gray;
background-color: $ui-gray;
width: 230px;
padding: 1rem;
height: 100%;
overflow: scroll;
text-shadow: none;
&.visible {
width: 20%;
min-width: 180px;
max-width: 230px;
}
&.hidden {
width: 10px;
}
@ -28,33 +23,6 @@
cursor: pointer;
}
.admin-content {
dl {
list-style: none;
dt {
margin: 2rem 0 1rem 0;
border-bottom: 1px solid $ui-dark-gray;
font-size: large;
font-weight: 700;
}
dd {
margin-left: 0;
}
}
ul {
padding: 0;
li {
margin: 0;
list-style: none;
}
}
}
.button-row {
display: flex;
font-size: small;

View file

@ -11,6 +11,7 @@ const classNames = require('classnames');
const GUI = require('scratch-gui').default;
const IntlGUI = injectIntl(GUI);
const AdminPanel = require('../../components/adminpanel/adminpanel.jsx');
const decorateText = require('../../lib/decorate-text.jsx');
const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Button = require('../../components/forms/button.jsx');
@ -45,6 +46,7 @@ const onKeyPress = e => {
const PreviewPresentation = ({
addToStudioOpen,
adminModalOpen,
assetHost,
backpackHost,
canAddToStudio,
@ -160,6 +162,18 @@ const PreviewPresentation = ({
return (
<div className="preview">
<AdminPanel
className={classNames('project-admin-panel', {
'modal-open': adminModalOpen
})}
>
<iframe
className={classNames('admin-iframe', {
'modal-open': adminModalOpen
})}
src={`/scratch2/${projectId}`}
/>
</AdminPanel>
{ projectInfo && projectInfo.author && projectInfo.author.id && (
<React.Fragment>
{banner}

View file

@ -35,6 +35,21 @@ $stage-width: 480px;
}
}
.admin-iframe {
position: absolute;
width: 252px;
height: 100%;
z-index: 100;
top: 0;
left: 0;
}
.admin-iframe.modal-open,
.project-admin-panel.modal-open {
width: 100%
}
.project-title {
font-size: 1.75rem;
font-weight: 500;

View file

@ -45,6 +45,7 @@ class Preview extends React.Component {
'handleFavoriteToggle',
'handleLoadMore',
'handleLoveToggle',
'handleMessage',
'handlePopState',
'handleReportClick',
'handleReportClose',
@ -79,6 +80,7 @@ class Preview extends React.Component {
this.state = {
addToStudioOpen: false,
adminModalOpen: false,
extensions: [],
favoriteCount: 0,
justShared: false,
@ -91,10 +93,12 @@ class Preview extends React.Component {
reportOpen: false,
singleCommentId: singleCommentId
};
this.addEventListeners();
/* In the beginning, if user is on mobile and landscape, go to fullscreen */
this.setScreenFromOrientation();
}
componentDidMount () {
this.addEventListeners();
}
componentDidUpdate (prevProps, prevState) {
if (this.state.projectId > 0 &&
((this.props.sessionStatus !== prevProps.sessionStatus &&
@ -138,10 +142,12 @@ class Preview extends React.Component {
addEventListeners () {
window.addEventListener('popstate', this.handlePopState);
window.addEventListener('orientationchange', this.setScreenFromOrientation);
window.addEventListener('message', this.handleMessage);
}
removeEventListeners () {
window.removeEventListener('popstate', this.handlePopState);
window.removeEventListener('orientationchange', this.setScreenFromOrientation);
window.removeEventListener('message', this.handleMessage);
}
fetchCommunityData () {
if (this.props.userPresent) {
@ -257,6 +263,18 @@ class Preview extends React.Component {
handleDeleteComment (id, topLevelCommentId) {
this.props.handleDeleteComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
}
handleMessage (messageEvent) {
if (messageEvent.data === 'showDialog') {
this.setState({
adminModalOpen: true
});
}
if (messageEvent.data === 'hideDialog') {
this.setState({
adminModalOpen: false
});
}
}
handleReportComment (id, topLevelCommentId) {
this.props.handleReportComment(this.state.projectId, id, topLevelCommentId, this.props.user.token);
}
@ -463,6 +481,7 @@ class Preview extends React.Component {
<Page>
<PreviewPresentation
addToStudioOpen={this.state.addToStudioOpen}
adminModalOpen={this.state.adminModalOpen}
assetHost={this.props.assetHost}
backpackHost={this.props.backpackHost}
canAddToStudio={this.props.canAddToStudio}

View file

@ -529,8 +529,9 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
>
{featured}
{this.props.isAdmin ? [
<AdminPanel key="admin-panel">
{this.props.isAdmin && (
<AdminPanel className="splash-admin-panel">
<dl>
<dt>Tools</dt>
<dd>
<ul>
@ -562,8 +563,32 @@ class SplashPresentation extends React.Component { // eslint-disable-line react/
</li>
</ul>
</dd>
<dt>Page Cache</dt>
<dd>
<ul className="cache-list">
<li>
<form
action="/scratch_admin/page/clear-anon-cache/"
method="post"
>
<input
name="path"
type="hidden"
value="/"
/>
<div className="button-row">
<span>For anonymous users:</span>
<Button type="submit">
<span>Clear</span>
</Button>
</div>
</form>
</li>
</ul>
</dd>
</dl>
</AdminPanel>
] : []}
)}
</div>
</div>
);

View file

@ -47,6 +47,33 @@
}
}
.splash-admin-panel {
dl {
list-style: none;
dt {
margin: 2rem 0 1rem 0;
border-bottom: 1px solid $ui-dark-gray;
font-size: large;
font-weight: 700;
}
dd {
margin-left: 0;
}
}
ul {
padding: 0;
li {
margin: 0;
list-style: none;
}
}
}
.modal-content.mod-confirmation {
width: 31.25rem;
}